Udostępnij za pomocą


Samouczek: wyszukiwanie ciągu przy użyciu wyrażeń regularnych (regex) w języku Java

Dotyczy: SQL Server 2019 (15.x) i nowsze wersje

W tym samouczku pokazano, jak za pomocą rozszerzeń języka SQL Server utworzyć klasę Języka Java, która odbiera dwie kolumny (identyfikator i tekst) z programu SQL Server oraz wyrażenie regularne (regex) jako parametr wejściowy. Klasa zwraca dwie kolumny z powrotem do programu SQL Server (identyfikator i tekst).

W przypadku danego tekstu w kolumnie tekstowej wysłanej do klasy Java kod sprawdza, czy dane wyrażenie regularne jest spełnione, i zwraca ten tekst wraz z oryginalnym identyfikatorem.

Ten przykładowy kod używa wyrażenia regularnego, które sprawdza, czy tekst zawiera słowo Java lub java.

Wymagania wstępne

Kompilacja wiersza polecenia jest javac wystarczająca na potrzeby tego samouczka.

Tworzenie przykładowych danych

Najpierw utwórz nową bazę danych i wypełnij tabelę testdata kolumnami ID i 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

Tworzenie klasy głównej

W tym kroku utwórz plik klasy o nazwie RegexSample.java i skopiuj następujący kod Java do tego pliku.

Ta klasa główna importuje zestaw SDK, co oznacza, że plik jar pobrany w kroku 1 musi być wykrywalny z tej klasy.

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();
    }
}

Kompilowanie i tworzenie pliku .jar

Spakuj .jar klasy i zależności do plików. Większość środowisk IDE języka Java (na przykład Eclipse lub IntelliJ) obsługuje generowanie plików podczas kompilowania lub kompilowania .jar projektu. Nadaj plikowi .jarregex.jarnazwę .

Jeśli nie używasz środowiska IDE języka Java, możesz ręcznie utworzyć .jar plik. Aby uzyskać więcej informacji, zobacz Create a Java .jar file from class files (Tworzenie pliku .jar Java z plików klas).

Uwaga / Notatka

W tym samouczku są używane pakiety. Wiersz package pkg; w górnej części klasy gwarantuje, że skompilowany kod zostanie zapisany w folderze podrzędnym o nazwie pkg. Jeśli używasz środowiska IDE, skompilowany kod zostanie automatycznie zapisany w tym folderze. Jeśli używasz metody javac do ręcznego kompilowania klas, musisz umieścić skompilowany kod w folderze pkg .

Tworzenie języka zewnętrznego

Musisz utworzyć język zewnętrzny w bazie danych. Język zewnętrzny jest obiektem o określonym zakresie bazy danych, co oznacza, że języki zewnętrzne, takie jak Java, muszą zostać utworzone dla każdej bazy danych, w której ma być używana.

Tworzenie języka zewnętrznego w systemie Windows

Jeśli używasz systemu Windows, wykonaj następujące kroki, aby utworzyć język zewnętrzny dla języka Java.

  1. Utwórz plik .zip zawierający rozszerzenie.

    W ramach konfiguracji programu SQL Server w systemie Windows plik rozszerzenia .zip Java jest instalowany w tej lokalizacji: [SQL Server install path]\MSSQL\Binn\java-lang-extension.zip. Ten plik zip zawiera plik javaextension.dll.

  2. Utwórz język zewnętrzny Java z pliku .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
    

Tworzenie języka zewnętrznego w systemie Linux

W ramach instalacji plik rozszerzenia .tar.gz jest zapisywany w następującej ścieżce: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz.

Aby utworzyć język zewnętrzny Java, uruchom następującą instrukcję języka T-SQL w systemie 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

Uprawnienia do wykonywania języka zewnętrznego

Aby wykonać kod Java, użytkownik musi mieć przyznane wykonywanie skryptów zewnętrznych w tym konkretnym języku.

Aby uzyskać więcej informacji, zobacz CREATE EXTERNAL LANGUAGE (TWORZENIE JĘZYKA ZEWNĘTRZNEgo).

Tworzenie bibliotek zewnętrznych

Utwórz bibliotekę zewnętrzną , aby utworzyć bibliotekę zewnętrzną dla plików .jar . Program SQL Server ma dostęp do .jar plików i nie musisz ustawiać żadnych specjalnych uprawnień na classpath.

W tym przykładzie utworzysz dwie biblioteki zewnętrzne. Jeden dla zestawu SDK i jeden dla kodu Java RegEx.

  1. Plik mssql-java-lang-extension.jar jar zestawu SDK jest instalowany w ramach programu SQL Server 2019 (15.x) i nowszych wersji w systemach Windows i Linux.

    • Domyślna ścieżka instalacji w systemie Windows: <instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar

    • Domyślna ścieżka instalacji w systemie Linux: /opt/mssql/lib/mssql-java-lang-extension.jar

    Kod jest również typu open source i można go znaleźć w repozytorium GitHub rozszerzeń języka programu SQL Server. Aby uzyskać więcej informacji, zobacz Zestaw MICROSOFT Extensibility SDK dla języka Java dla programu SQL Server.

  2. Utwórz zewnętrzną bibliotekę dla zestawu SDK.

    CREATE EXTERNAL LIBRARY sdk
    FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar')
    WITH (LANGUAGE = 'Java');
    GO
    
  3. Utwórz bibliotekę zewnętrzną dla kodu RegEx.

    CREATE EXTERNAL LIBRARY regex
    FROM (CONTENT = '<path>/regex.jar')
    WITH (LANGUAGE = 'Java');
    GO
    

Ustawianie uprawnień

Uwaga / Notatka

Pomiń ten krok, jeśli używasz bibliotek zewnętrznych w poprzednim kroku. Zalecanym sposobem jest utworzenie zewnętrznej biblioteki na podstawie .jar pliku.

Jeśli nie chcesz używać bibliotek zewnętrznych, musisz ustawić niezbędne uprawnienia. Wykonanie skryptu kończy się powodzeniem tylko wtedy, gdy tożsamości procesu mają dostęp do kodu. Więcej informacji o ustawianiu uprawnień można znaleźć w przewodniku instalacji.

W systemie Linux

Przyznaj użytkownikowi uprawnienia do odczytu/wykonywania dla ścieżki mssql_satellite klas.

W systemie Windows

Udziel uprawnień "Odczyt i wykonaj" grupie SQLRUserGroup oraz identyfikatorowi SID Wszystkich pakietów aplikacji w folderze zawierającym skompilowany kod Java.

Całe drzewo musi mieć uprawnienia od głównego elementu nadrzędnego do ostatniego folderu podrzędnego.

  1. Kliknij prawym przyciskiem myszy folder (na przykład C:\myJavaCode) i wybierz pozycję Zabezpieczenia właściwości>.
  2. Wybierz Edytuj.
  3. Wybierz Dodaj.
  4. W obszarze Wybierz użytkowników, komputer, konta usług lub grupy:
    1. Wybierz pozycję Typy obiektów i upewnij się, że wybrano wbudowane zasady zabezpieczeń i grupy .
    2. Wybierz pozycję Lokalizacje , aby wybrać nazwę komputera lokalnego w górnej części listy.
  5. Wprowadź ciąg SQLRUserGroup, zaznacz nazwę i wybierz przycisk OK , aby dodać grupę.
  6. Wprowadź WSZYSTKIE PAKIETY APLIKACJI, zaznacz nazwę i wybierz przycisk OK , aby dodać. Jeśli nazwa nie zostanie rozpoznana, ponownie przejdź do kroku Lokalizacje. Identyfikator SID jest lokalny dla twojej maszyny.

Upewnij się, że obie tożsamości zabezpieczeń mają uprawnienia Odczyt i Wykonywanie w folderze i w podfolderze pkg .

Wywoływanie klasy Java

Utwórz procedurę składowaną, która wywołuje sp_execute_external_script wywołanie kodu Java z programu SQL Server. W parametrze zdefiniuj script , które package.class chcesz wywołać. W poniższym kodzie klasa należy do pakietu o nazwie i pliku klasy o nazwie pkgRegexSample.java.

Uwaga / Notatka

Kod nie definiuje metody do wywołania. Domyślnie metoda będzie wywoływana execute . Oznacza to, że musisz postępować zgodnie z interfejsem zestawu SDK i zaimplementować metodę execute w klasie Java, jeśli chcesz mieć możliwość wywołania klasy z programu SQL Server.

Procedura składowana przyjmuje zapytanie wejściowe (wejściowy zestaw danych) i wyrażenie regularne i zwraca wiersze spełniające podane wyrażenie regularne. Używa wyrażenia regularnego [Jj]ava , które sprawdza, czy tekst zawiera słowo Java lub 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
    EXECUTE 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

Results

Po wykonaniu wywołania należy uzyskać zestaw wyników z dwoma wierszami.

Zrzut ekranu przedstawiający przykład Wyniki z języka Java.

Jeśli wystąpi błąd

  • Podczas kompilowania klas pkg podfolder powinien zawierać skompilowany kod dla wszystkich trzech klas.

  • Jeśli nie używasz bibliotek zewnętrznych, sprawdź uprawnienia do każdego folderu z root folderu do pkg podfolderu, aby upewnić się, że tożsamości zabezpieczeń uruchomione w procesie zewnętrznym mają uprawnienia do odczytywania i wykonywania kodu.