Megosztás a következőn keresztül:


Oktatóanyag: Sztring keresése normál kifejezésekkel (regex) Java-ban

A következőkre vonatkozik: SQL Server 2019 (15.x) és újabb verziók

Ez az oktatóanyag bemutatja, hogyan hozhat létre olyan Java-osztályt az SQL Server nyelvkiterjesztéseinek használatával, amelyek két oszlopot (azonosítót és szöveget) kapnak az SQL Servertől, valamint egy regex regex kifejezést bemeneti paraméterként. Az osztály két oszlopot ad vissza az SQL Servernek (azonosító és szöveg).

A Java-osztálynak küldött szövegoszlop adott szövege esetén a kód ellenőrzi, hogy a megadott reguláris kifejezés teljesül-e, és az eredeti azonosítóval együtt adja vissza a szöveget.

Ez a mintakód egy reguláris kifejezést használ, amely ellenőrzi, hogy egy szöveg tartalmazza-e a szót Java vagy javaa szót.

Előfeltételek

Ehhez az oktatóanyaghoz elegendő a parancssori fordítás javac .

Mintaadatok létrehozása

Először hozzon létre egy új adatbázist, és töltse fel a testdata táblázatot oszlopokkal és text oszlopokkalID.

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

A főosztály létrehozása

Ebben a lépésben hozzon létre egy osztályfájlt, RegexSample.java és másolja a következő Java-kódot a fájlba.

Ez a főosztály importálja az SDK-t, ami azt jelenti, hogy az 1. lépésben letöltött jar-fájlt ebből az osztályból kell felderíteni.

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

.jar-fájl fordítása és létrehozása

Csomagolja be az osztályokat és függőségeket egy .jar fájlba. A legtöbb Java-azonosító (például Eclipse vagy IntelliJ) támogatja a fájlok generálásának .jar támogatását a projekt létrehozásakor vagy fordításakor. Nevezze el a .jar fájlt regex.jar.

Ha nem Java IDE-t használ, manuálisan is létrehozhat egy .jar fájlt. További információ: Java-.jar-fájl létrehozása osztályfájlokból.

Megjegyzés:

Ez az oktatóanyag csomagokat használ. Az package pkg; osztály tetején lévő sor biztosítja, hogy a lefordított kód egy úgynevezett pkgalmappába legyen mentve. IDE használata esetén a program automatikusan ebbe a mappába menti a lefordított kódot. Ha manuálisan fordítja javac le az osztályokat, a lefordított kódot a pkg mappába kell helyeznie.

Külső nyelv létrehozása

Létre kell hoznia egy külső nyelvet az adatbázisban. A külső nyelv egy adatbázis-hatókörű objektum, ami azt jelenti, hogy minden olyan adatbázishoz létre kell hozni külső nyelveket, mint a Java.

Külső nyelv létrehozása Windows rendszeren

Ha Windowst használ, az alábbi lépéseket követve hozzon létre egy külső nyelvet a Java számára.

  1. Hozzon létre egy .zip kiterjesztést tartalmazó fájlt.

    A Windows SQL Server telepítésének részeként a Java-bővítményfájl .zip a következő helyen van telepítve: [SQL Server install path]\MSSQL\Binn\java-lang-extension.zip. Ez a zip-fájl tartalmazza a javaextension.dll.

  2. Hozzon létre egy külső nyelvű Java-t a .zip fájlból:

    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
    

Külső nyelv létrehozása Linuxon

A telepítés részeként a bővítményfájl .tar.gz a következő elérési úton lesz mentve: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz.

Külső nyelvű Java létrehozásához futtassa a következő T-SQL-utasítást Linuxon:

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

Külső nyelv végrehajtásának engedélyei

A Java-kód végrehajtásához a felhasználónak külső szkriptvégrehajtást kell biztosítani az adott nyelven.

További információ: CREATE EXTERNAL LANGUAGE.

Külső kódtárak létrehozása

A CREATE EXTERNAL LIBRARY használatával külső tárat hozhat létre a .jar fájlokhoz. Az SQL Server hozzáfér a .jar fájlokhoz, és nem kell külön engedélyeket beállítania a classpath.

Ebben a mintában két külső kódtárat hoz létre. Egyet az SDK-hoz, egyet pedig a RegEx Java-kódhoz.

  1. Az SDK jar-fájl mssql-java-lang-extension.jar az SQL Server 2019 (15.x) és újabb verzióinak részeként van telepítve Windows és Linux rendszeren is.

    • Alapértelmezett telepítési útvonal Windows rendszeren: <instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar

    • Alapértelmezett telepítési útvonal Linuxon: /opt/mssql/lib/mssql-java-lang-extension.jar

    A kód nyílt forráskódú is, és megtalálható az SQL Server Language Extensions GitHub-adattárban. További információ: Microsoft Extensibility SDK for Java for SQL Server.

  2. Hozzon létre egy külső kódtárat az SDK-hoz.

    CREATE EXTERNAL LIBRARY sdk
    FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar')
    WITH (LANGUAGE = 'Java');
    GO
    
  3. Hozzon létre egy külső kódtárat a RegEx-kódhoz.

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

Engedélyek beállítása

Megjegyzés:

Hagyja ki ezt a lépést, ha az előző lépésben külső kódtárakat használ. A javasolt módszer egy külső tár létrehozása a .jar fájlból.

Ha nem szeretne külső kódtárakat használni, be kell állítania a szükséges engedélyeket. A szkript végrehajtása csak akkor sikeres, ha a folyamatidentitások hozzáférnek a kódhoz. Az engedélyek beállításáról a telepítési útmutatóban talál további információt.

Linuxon

Olvasási/végrehajtási engedélyeket adhat a felhasználónak mssql_satellite az osztályúton.

Windows rendszeren

Adjon "Olvasási és végrehajtási" engedélyeket az SQLRUserGroupnak és az Összes alkalmazáscsomag SID-jének a lefordított Java-kódot tartalmazó mappában.

A teljes fának rendelkeznie kell engedélyekkel a gyökér szülőtől az utolsó almappáig.

  1. Kattintson a jobb gombbal a mappára (például ) és C:\myJavaCodeválassza a Tulajdonságok>biztonsága lehetőséget.
  2. Válassza a Szerkesztés lehetőséget.
  3. Válassza a Hozzáadás lehetőséget.
  4. Felhasználók , számítógépek, szolgáltatásfiókok vagy csoportok kiválasztásakor:
    1. Válassza az Objektumtípusok lehetőséget , és győződjön meg arról , hogy a beépített biztonsági alapelvek és csoportok ki vannak választva.
    2. Válassza a Helyek lehetőséget a helyi számítógép nevének kiválasztásához a lista tetején.
  5. Írja be az SQLRUserGroup nevet, ellenőrizze a nevet, és kattintson az OK gombra a csoport hozzáadásához.
  6. Adja meg az ÖSSZES ALKALMAZÁSCSOMAGot, ellenőrizze a nevet, és válassza az OK gombot a hozzáadáshoz. Ha a név nem oldható fel, tekintse meg újra a Helyek lépést. A SID a gép helyi azonosítója.

Győződjön meg arról, hogy mindkét biztonsági identitás olvasási és végrehajtási engedélyekkel rendelkezik a mappán és az pkg almappán.

A Java-osztály meghívása

Hozzon létre egy tárolt eljárást, amely meghívja sp_execute_external_script a Java-kódot az SQL Serverről. A paraméterben script adja meg, hogy melyiket package.class szeretné meghívni. Az alábbi kódban az osztály egy hívott pkg csomaghoz és egy osztályfájlhoz RegexSample.javatartozik.

Megjegyzés:

A kód nem határozza meg, hogy melyik metódust kell meghívni. Alapértelmezés szerint a rendszer meghívja a execute metódust. Ez azt jelenti, hogy követnie kell az SDK-felületet, és végre kell hajtania egy végrehajtási metódust a Java-osztályban, ha meg szeretné hívni az osztályt az SQL Serverről.

A tárolt eljárás egy bemeneti lekérdezést (bemeneti adatkészletet) és egy reguláris kifejezést használ, és visszaadja azokat a sorokat, amelyek teljesítették az adott reguláris kifejezést. Egy reguláris kifejezést [Jj]ava használ, amely ellenőrzi, hogy egy szöveg tartalmazza-e a szót vagy javaa szótJava.

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

A hívás végrehajtása után két sorból álló eredményhalmazt kell kapnia.

Képernyőkép a Java-minta eredményeiről.

Ha hibaüzenet jelenik meg

  • Az osztályok lefordításakor az pkg almappának tartalmaznia kell mind a három osztály lefordított kódját.

  • Ha nem használ külső kódtárakat, ellenőrizze az egyes mappák engedélyeit az almappától az root almappáig pkg , és győződjön meg arról, hogy a külső folyamatot futtató biztonsági identitások rendelkeznek engedéllyel a kód olvasására és végrehajtására.