Tutoriel : Rechercher une chaîne à l’aide d’expressions régulières (regex) en Java
S’applique à : SQL Server 2019 (15.x) et versions ultérieures
Ce tutoriel vous montre comment utiliser les extensions de langage SQL Server pour créer une classe Java qui reçoit deux colonnes (ID et text) de SQL Server et une expression régulière (regex) comme paramètre d’entrée. La classe retourne deux colonnes à SQL Server (ID et text).
Pour un texte donné dans la colonne de texte envoyée à la classe Java, le code vérifie si l’expression régulière donnée est satisfaite, puis retourne ce texte avec l’ID d’origine.
Cet exemple de code utilise une expression régulière qui vérifie si un texte contient le mot Java
ou java
.
Prérequis
Instance de moteur de base de données sur SQL Server 2019 (15.x) et versions ultérieures, avec cadre d’extensibilité et extension de programmation Java sur Windows ou sur Linux. Pour plus d’informations, consultez Extension de langage dans SQL Server. Pour plus d’informations sur les exigences en matière de codage, consultez Comment appeler le runtime Java dans les extensions de langage SQL Server.
SQL Server Management Studio ou Azure Data Studio pour exécuter le code T-SQL.
Java SE Development Kit (JDK) 8 ou JRE 8 sur Windows ou Linux.
Le fichier
mssql-java-lang-extension.jar
du kit SDK d’extensibilité Microsoft pour Java pour SQL Server.
Pour ce tutoriel, la compilation à partir de la ligne de commande avec javac
suffit.
Créer des exemples de données
Commencez par créer une base de données et remplissez une table testdata
avec les colonnes ID
et text
.
CREATE DATABASE javatest;
GO
USE javatest;
GO
CREATE TABLE testdata (
[id] INT NOT NULL,
[text] NVARCHAR(100) NOT NULL
);
GO
-- Insert data into test table
INSERT INTO testdata ([id], [text])
VALUES (1, 'This sentence contains java');
INSERT INTO testdata ([id], [text])
VALUES (2, 'This sentence does not');
INSERT INTO testdata ([id], [text])
VALUES (3, 'I love Java!');
GO
Créer la classe principale
Dans cette étape, créez un fichier de classe appelé RegexSample.java
et copiez le code Java suivant dans ce fichier.
Cette classe principale importe le kit de développement logiciel (SDK), ce qui signifie que le fichier jar téléchargé à l’étape 1 doit être détectable à partir de cette classe.
package pkg;
import com.microsoft.sqlserver.javalangextension.PrimitiveDataset;
import com.microsoft.sqlserver.javalangextension.AbstractSqlServerExtensionExecutor;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.regex.*;
public class RegexSample extends AbstractSqlServerExtensionExecutor {
private Pattern expr;
public RegexSample() {
// Setup the expected extension version, and class to use for input and output dataset
executorExtensionVersion = SQLSERVER_JAVA_LANG_EXTENSION_V1;
executorInputDatasetClassName = PrimitiveDataset.class.getName();
executorOutputDatasetClassName = PrimitiveDataset.class.getName();
}
public PrimitiveDataset execute(PrimitiveDataset input, LinkedHashMap<String, Object> params) {
// Validate the input parameters and input column schema
validateInput(input, params);
int[] inIds = input.getIntColumn(0);
String[] inValues = input.getStringColumn(1);
int rowCount = inValues.length;
String regexExpr = (String)params.get("regexExpr");
expr = Pattern.compile(regexExpr);
System.out.println("regex expression: " + regexExpr);
// Lists to store the output data
LinkedList<Integer> outIds = new LinkedList<Integer>();
LinkedList<String> outValues = new LinkedList<String>();
// Evaluate each row
for(int i = 0; i < rowCount; i++) {
if (check(inValues[i])) {
outIds.add(inIds[i]);
outValues.add(inValues[i]);
}
}
int outputRowCount = outValues.size();
int[] idOutputCol = new int[outputRowCount];
String[] valueOutputCol = new String[outputRowCount];
// Convert the list of output columns to arrays
outValues.toArray(valueOutputCol);
ListIterator<Integer> it = outIds.listIterator(0);
int rowId = 0;
System.out.println("Output data:");
while (it.hasNext()) {
idOutputCol[rowId] = it.next().intValue();
System.out.println("ID: " + idOutputCol[rowId] + " Value: " + valueOutputCol[rowId]);
rowId++;
}
// Construct the output dataset
PrimitiveDataset output = new PrimitiveDataset();
output.addColumnMetadata(0, "ID", java.sql.Types.INTEGER, 0, 0);
output.addColumnMetadata(1, "Text", java.sql.Types.NVARCHAR, 0, 0);
output.addIntColumn(0, idOutputCol, null);
output.addStringColumn(1, valueOutputCol);
return output;
}
private void validateInput(PrimitiveDataset input, LinkedHashMap<String, Object> params) {
// Check for the regex expression input parameter
if (params.get("regexExpr") == null) {
throw new IllegalArgumentException("Input parameter 'regexExpr' is not found");
}
// The expected input schema should be at least 2 columns, (INTEGER, STRING)
if (input.getColumnCount() < 2) {
throw new IllegalArgumentException("Unexpected input schema, schema should be an (INTEGER, NVARCHAR or VARCHAR)");
}
// Check that the input column types are expected
if (input.getColumnType(0) != java.sql.Types.INTEGER &&
(input.getColumnType(1) != java.sql.Types.VARCHAR && input.getColumnType(1) == java.sql.Types.NVARCHAR )) {
throw new IllegalArgumentException("Unexpected input schema, schema should be an (INTEGER, NVARCHAR or VARCHAR)");
}
}
private boolean check(String text) {
Matcher m = expr.matcher(text);
return m.find();
}
}
Compiler et créer un fichier .jar
Empaquetez vos classes et dépendances dans des fichiers .jar
. La plupart des IDE Java (par exemple, Eclipse ou IntelliJ) prennent en charge la génération de fichiers .jar
quand vous générez ou compilez le projet. Nommez le fichier .jar
en tant que regex.jar
.
Si vous n’utilisez pas un IDE Java, vous pouvez créer manuellement un fichier .jar
. Pour plus d’informations, consultez Créer un fichier .jar Java à partir de fichiers de classe.
Remarque
Ce tutoriel utilise des packages. La ligne package pkg;
en haut de la classe garantit que le code compilé est enregistré dans un sous-dossier appelé pkg
. Si vous utilisez un IDE, le code compilé est automatiquement enregistré dans ce dossier. Si vous utilisez javac
pour compiler manuellement les classes, vous devez placer le code compilé dans le dossier pkg
.
Créer un langage externe
Vous devez créer un langage externe dans la base de données. Le langage externe est un objet délimité à une base de données, ce qui signifie qu’un langage externe comme Java doit être créé pour chaque base de données où vous souhaitez l’utiliser.
Créer un langage externe sur Windows
Si vous utilisez Windows, suivez les étapes suivante pour créer un langage externe pour Java.
Créez un fichier .zip contenant l’extension.
Dans le cadre de l’installation de SQL Server sur Windows, le fichier
.zip
de l’extension Java est enregistré à l’emplacement[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip
. Ce fichier zip contientjavaextension.dll
.Créez un langage externe pour Java à partir du fichier .zip :
CREATE EXTERNAL LANGUAGE Java FROM (CONTENT = N'[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip', FILE_NAME = 'javaextension.dll', ENVIRONMENT_VARIABLES = N'{"JRE_HOME":"<path to JRE>"}' ); GO
Créer un langage externe sur Linux
Dans le cadre de l’installation, le fichier .tar.gz
de l’extension est enregistré dans le chemin d’accès /opt/mssql-extensibility/lib/java-lang-extension.tar.gz
.
Pour créer un langage externe pour Java, exécutez l’instruction T-SQL suivante sur Linux :
CREATE EXTERNAL LANGUAGE Java
FROM (CONTENT = N'/opt/mssql-extensibility/lib/java-lang-extension.tar.gz', file_name = 'javaextension.so',
ENVIRONMENT_VARIABLES = N'{"JRE_HOME":"<path to JRE>"}' );
GO
Autorisations pour exécuter le langage externe
Pour exécuter du code Java, un utilisateur doit avoir l’autorisation d’exécuter un script externe sur ce langage spécifique.
Pour plus d’informations, consultez CRÉER UN LANGAGE EXTERNE.
Créer des bibliothèques externes
Utilisez CREATE EXTERNAL LIBRARY pour créer une bibliothèque externe pour vos fichiers .jar
. SQL Server ayant accès aux fichiers .jar
, vous n’avez pas besoin de définir d’autorisations spéciales pour classpath
.
Dans cet exemple, vous créez deux bibliothèques externes : une pour le kit SDK et une pour le code Java RegEx.
Le fichier jar
mssql-java-lang-extension.jar
du kit de développement logiciel (SDK) est installé dans le cadre de SQL Server 2019 (15.x) et versions ultérieures, sur Windows et Linux.Chemin d’installation par défaut sur Windows :
<instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar
Chemin d’installation par défaut sur Linux :
/opt/mssql/lib/mssql-java-lang-extension.jar
Le code est open source et se trouve dans le dépôt GitHub des extensions de langage SQL Server. Pour plus d’informations, consultez SDK d’extensibilité Microsoft pour Java pour SQL Server.
Créez une bibliothèque externe pour le kit SDK.
CREATE EXTERNAL LIBRARY sdk FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar') WITH (LANGUAGE = 'Java'); GO
Créez une bibliothèque externe pour le code RegEx.
CREATE EXTERNAL LIBRARY regex FROM (CONTENT = '<path>/regex.jar') WITH (LANGUAGE = 'Java'); GO
Définir des autorisations
Notes
Ignorez cette étape si vous avez opté pour des bibliothèques externes à l’étape précédente. La méthode recommandée consiste à créer une bibliothèque externe à partir de votre fichier .jar
.
Si vous ne souhaitez pas utiliser de bibliothèques externes, vous devez définir les autorisations nécessaires. L’exécution du script ne réussit que si les identités du processus ont accès à votre code. Pour plus d’informations sur la définition d’autorisations, consultez le guide d’installation.
Sur Linux
Accordez des autorisations de lecture et d’exécution sur classpath à l’utilisateur mssql_satellite
.
Sur Windows
Accordez des autorisations de lecture et d’exécution à SQLRUserGroup et au SID Tous les packages d’application sur le dossier contenant votre code Java compilé.
L’arborescence entière doit avoir les autorisations, du parent racine au dernier sous-dossier.
- Cliquez avec le bouton droit sur le dossier (par exemple,
C:\myJavaCode
) et choisissez Propriétés>Sécurité. - Sélectionnez Modifier.
- Sélectionnez Ajouter.
- Dans Sélectionner les utilisateurs, les ordinateurs, les comptes de service ou les groupes :
- Sélectionnez Types d’objets et Principes de sécurité intégrés, puis Groupes.
- Sélectionnez Emplacements pour choisir le nom de l’ordinateur local en haut de la liste.
- Saisissez SQLRUserGroup, vérifiez le nom, puis cliquez sur OKpour ajouter le groupe.
- Saisissez TOUS LES PACKAGES D’APPLICATION, vérifiez le nom, puis cliquez sur OK pour ajouter. Si le nom n’est pas résolu, revisitez l’étape Emplacements. Le SID est local sur votre ordinateur.
Vérifiez que les deux identités de sécurité ont des autorisations Lire et exécuter sur le dossier et le sous-dossier pkg
.
Appeler la classe Java
Créez une procédure stockée qui appelle sp_execute_external_script
pour appeler le code Java à partir de SQL Server. Dans le paramètre script
, définissez le package.class
à appeler. Dans le code suivant, la classe appartient à un package appelé pkg
et à un fichier de classe appelé RegexSample.java
.
Remarque
Le code ne définit pas la méthode à appeler. Par défaut, la méthode execute
est appelée. Cela signifie que vous devez suivre l’interface du kit SDK et implémenter une méthode execute dans votre classe Java pour pouvoir appeler la classe à partir de SQL Server.
La procédure stockée prend une requête d’entrée (jeu de données d’entrée) et une expression régulière, puis retourne les lignes qui satisfont l’expression régulière donnée. Elle utilise une expression régulière [Jj]ava
qui vérifie si un texte contient le mot Java
ou java
.
CREATE OR ALTER PROCEDURE [dbo].[java_regex]
@expr NVARCHAR(200), @query NVARCHAR(400)
AS
BEGIN
--Call the Java program by giving the package.className in @script
--The method invoked in the Java code is always the "execute" method
EXEC sp_execute_external_script @language = N'Java',
@script = N'pkg.RegexSample',
@input_data_1 = @query,
@params = N'@regexExpr nvarchar(200)',
@regexExpr = @expr
WITH result sets((
ID INT,
TEXT NVARCHAR(100)
));
END
GO
--Now execute the above stored procedure and provide the regular expression and an input query
EXECUTE [dbo].[java_regex] N'[Jj]ava',
N'SELECT id, text FROM testdata'
GO
Résultats
Après l’exécution de l’appel, vous devez obtenir un jeu de résultats avec deux lignes.
Si vous obtenez une erreur
Lorsque vous compilez vos classes, le sous-dossier
pkg
doit contenir le code compilé des trois classes.Si vous n’utilisez pas de bibliothèques externes, examinez les autorisations sur chaque dossier, de
root
au sous-dossierpkg
, pour vérifier que les identités de sécurité qui exécutent le processus externe sont autorisées à lire et à exécuter votre code.