Esercitazione: cercare una stringa usando espressioni regolari (regex) in Java
Si applica a: SQL Server 2019 (15.x) e versioni successive
Questa esercitazione illustra come usare le estensioni del linguaggio di SQL Server per creare una classe Java che riceve due colonne (ID e testo) da SQL Server e un'espressione regolare (regex) come parametro di input. La classe restituisce due colonne (ID e testo) a SQL Server.
Per un determinato testo nella colonna di testo inviata alla classe Java, il codice controlla se l'espressione regolare specificata viene soddisfatta e restituisce tale testo insieme all'ID originale.
Il codice di esempio usa un'espressione regolare che controlla se un testo contiene la parola Java
o java
.
Prerequisiti
Istanza del motore di database su SQL Server 2019 (15.x) e versioni successive, con il framework di estensibilità e l'estensione di programmazione Java su Windows o Linux. Per altre informazioni, vedere Estensioni del linguaggio di SQL Server. Per altre informazioni sui requisiti di codifica, vedere Come chiamare il runtime Java nelle estensioni del linguaggio di SQL Server.
SQL Server Management Studio o Azure Data Studio per l'esecuzione di T-SQL.
Java SE Development Kit (JDK) 8 o JRE 8 in Windows o Linux.
Il file
mssql-java-lang-extension.jar
di Microsoft Extensibility SDK per Java per SQL Server.
Per questa esercitazione è sufficiente la compilazione da riga di comando tramite javac
.
Creare dati di esempio
Per prima cosa, creare un nuovo database e popolare una tabella testdata
con le colonne ID
e 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
Creare la classe principale
In questo passaggio creare un file di classe denominato RegexSample.java
e copiare il codice Java seguente nel file.
Questa classe principale importa l'SDK, il che significa che il file con estensione jar scaricato nel passaggio 1 deve essere individuabile da questa 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();
}
}
Compilare e creare un file con estensione jar
Assemblare le classi e le dipendenze in un file .jar
. La maggior parte degli ambienti IDE Java (ad esempio, Eclipse o IntelliJ) supporta la generazione di file .jar
quando si crea o si compila il progetto. Assegnare un nome al .jar
file regex.jar
.
Se non si usa un ambiente IDE Java, è possibile creare manualmente un file .jar
. Per altre informazioni, vedere Creare un file .jar di Java dai file di classe.
Nota
In questa esercitazione vengono usati i pacchetti. La riga package pkg;
nella parte superiore della classe garantisce che il codice compilato venga salvato in una sottocartella denominata pkg
. Se si usa un IDE, il codice compilato viene salvato automaticamente in questa cartella. Se si usa javac
per compilare manualmente le classi, è necessario inserire il codice compilato nella cartella pkg
.
Creare un linguaggio esterno
È necessario creare un linguaggio esterno nel database. Il linguaggio esterno è un oggetto con ambito di database, il che significa che è necessario creare linguaggi esterni come Java per ogni database in cui si vuole usarlo.
Creare un linguaggio esterno in Windows
Se si usa Windows, attenersi alla procedura seguente per creare un linguaggio esterno per Java.
Creare un file ZIP contenente l'estensione.
Come parte del programma di installazione di SQL Server in Windows, il file
.zip
dell'estensione Java è installato in questo percorso:[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip
. Questo file ZIP contienejavaextension.dll
.Creare un linguaggio esterno Java dal file 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
Creare un linguaggio esterno in Linux
Come parte del programma di installazione, il file .tar.gz
dell'estensione viene salvato nel percorso seguente: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz
.
Per creare un linguaggio esterno Java, eseguire l'istruzione T-SQL seguente in 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
Autorizzazioni per eseguire il linguaggio esterno
Per eseguire il codice Java, un utente deve disporre dell'autorizzazione per l'esecuzione di script esterni in quel linguaggio specifico.
Per altre informazioni, vedere CREATE EXTERNAL LANGUAGE.
Creare librerie esterne
Usare CREATE EXTERNAL LIBRARY per creare una libreria esterna per i file .jar
. SQL Server ha accesso ai file .jar
e non è necessario impostare autorizzazioni speciali per il classpath
.
In questo esempio si creeranno due librerie esterne. una per l'SDK e l'altra per il codice Java RegEx.
Il file jar dell'SDK
mssql-java-lang-extension.jar
viene installato come parte di SQL Server 2019 (15.x) e versioni successive, sia su Windows che su Linux.Percorso di installazione predefinito in Windows:
<instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar
Percorso di installazione predefinito in Linux:
/opt/mssql/lib/mssql-java-lang-extension.jar
Il codice è anche open source ed è disponibile nel repository GitHub delle estensioni del linguaggio di SQL Server. Per altre informazioni, vedere Microsoft Extensibility SDK per Java per Microsoft SQL Server.
Creare una libreria esterna per l'SDK.
CREATE EXTERNAL LIBRARY sdk FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar') WITH (LANGUAGE = 'Java'); GO
Creare una libreria esterna per il codice RegEx.
CREATE EXTERNAL LIBRARY regex FROM (CONTENT = '<path>/regex.jar') WITH (LANGUAGE = 'Java'); GO
Impostare le autorizzazioni
Nota
Ignorare questo passaggio se si usano librerie esterne nel passaggio precedente. Il metodo consigliato consiste nel creare una libreria esterna dal file .jar
.
Se non si vogliono usare librerie esterne, sarà necessario impostare le autorizzazioni richieste. L'esecuzione dello script ha esito positivo solo se le identità del processo hanno accesso al codice. Per altre informazioni sull'impostazione di autorizzazioni, vedere la guida all'installazione.
In Linux
Concedere autorizzazioni di lettura/esecuzione per il classpath all'utente mssql_satellite
.
In Windows
Concedere autorizzazioni di lettura ed esecuzione a SQLRUserGroup e l'ID di sicurezza per Tutti i pacchetti applicazioni per la cartella contenente il codice Java compilato.
L'intero albero deve avere le autorizzazioni, dal padre di livello radice all'ultima sottocartella.
- Fare clic con il pulsante destro del mouse sulla cartella, ad esempio
C:\myJavaCode
, e quindi scegliere Proprietà>Sicurezza. - Seleziona Modifica
- Selezionare Aggiungi.
- In Seleziona utenti, computer, account servizio o gruppi:
- Fare clic su Tipi di oggetto e assicurarsi che siano selezionati i principi di sicurezza predefiniti e i gruppi.
- Fare clic su Percorsi per selezionare il nome del computer locale nella parte superiore dell'elenco.
- Immettere SQLRUserGroup, verificare il nome e fare clic su OK per aggiungere il gruppo.
- Immettere TUTTI I PACCHETTI DELL'APPLICAZIONE, verificare il nome e fare clic su OK per aggiungere. Se il nome non viene risolto, rivedere il passaggio relativo ai Percorsi. L'ID di sicurezza è locale per il computer in uso.
Verificare che entrambe le identità di sicurezza dispongano delle autorizzazioni Lettura ed esecuzione per la cartella e la sottocartella pkg
.
Chiamare la classe Java
Creare una stored procedure che chiama sp_execute_external_script
per chiamare il codice Java da SQL Server. Nel parametro script
definire quale package.class
si vuole chiamare. Nel codice seguente la classe appartiene a un pacchetto denominato pkg
e a un file di classe denominato RegexSample.java
.
Nota
Il codice non definisce il metodo da chiamare. Per impostazione predefinita, verrà chiamato il metodo execute
. Ciò significa che è necessario seguire l'interfaccia dell'SDK e implementare un metodo execute nella classe Java, se si vuole essere in grado di chiamare la classe da SQL Server.
La stored procedure accetta una query di input (set di dati di input) e un'espressione regolare e restituisce le righe che hanno soddisfatto l'espressione regolare specificata. Viene usata un'espressione regolare [Jj]ava
che controlla se un testo contiene la parola Java
o 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
Risultati
Dopo aver eseguito la chiamata, si dovrebbe ottenere un set di risultati con due delle righe.
Se si riceve un errore
Quando si compilano le classi, la sottocartella
pkg
deve contenere il codice compilato per tutte e tre le classi.Se non si usano librerie esterne, controllare le autorizzazioni per ogni cartella, dalla sottocartella
root
apkg
, per assicurarsi che le identità di sicurezza che eseguono il processo esterno dispongano delle autorizzazioni per la lettura e l'esecuzione del codice.