Tutorial: Mencari string menggunakan ekspresi reguler (regex) di Java

Berlaku untuk: SQL Server 2019 (15.x) dan versi yang lebih baru

Tutorial ini menunjukkan kepada Anda cara menggunakan Ekstensi Bahasa SQL Server untuk membuat kelas Java yang menerima dua kolom (ID dan teks) dari SQL Server dan ekspresi reguler (regex) sebagai parameter input. Kelas mengembalikan dua kolom kembali ke SQL Server (ID dan teks).

Untuk teks tertentu di kolom teks yang dikirim ke kelas Java, kode memeriksa apakah ekspresi reguler yang diberikan terpenuhi, dan mengembalikan teks tersebut bersama dengan ID asli.

Kode sampel ini menggunakan ekspresi reguler yang memeriksa apakah teks berisi kata Java atau java.

Prasyarat

Kompilasi baris perintah menggunakan javac cukup untuk tutorial ini.

Membuat data sampel

Pertama, buat database baru dan isi testdata tabel dengan ID kolom dan 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

Membuat kelas utama

Dalam langkah ini, buat file kelas yang disebut RegexSample.java dan salin kode Java berikut ke dalam file tersebut.

Kelas utama ini mengimpor SDK, yang berarti bahwa file jar yang diunduh di langkah1 perlu ditemukan dari kelas ini.

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

Mengkompilasi dan membuat file .jar

Kemas kelas dan dependensi Anda ke dalam file .jar . Sebagian besar ID Java (misalnya, Eclipse atau IntelliJ) mendukung pembuatan .jar file saat Anda membuat atau mengkompilasi proyek. Beri nama .jar file regex.jar.

Jika Anda tidak menggunakan Java IDE, Anda dapat membuat .jar file secara manual. Untuk informasi selengkapnya, lihat Membuat file jar Java dari file kelas.

Catatan

Tutorial ini menggunakan paket. Baris package pkg; di bagian atas kelas memastikan bahwa kode yang dikompilasi disimpan dalam sub folder yang disebut pkg. Jika Anda menggunakan IDE, kode yang dikompilasi secara otomatis disimpan dalam folder ini. Jika Anda menggunakan javac untuk mengkompilasi kelas secara manual, Anda perlu menempatkan kode yang dikompilasi di pkg folder.

Membuat bahasa eksternal

Anda perlu membuat bahasa eksternal dalam database. Bahasa eksternal adalah objek cakupan database, yang berarti bahwa bahasa eksternal seperti Java perlu dibuat untuk setiap database tempat Anda ingin menggunakannya.

Membuat bahasa eksternal di Windows

Jika Anda menggunakan Windows, ikuti langkah-langkah ini untuk membuat bahasa eksternal untuk Java.

  1. Buat file .zip yang berisi ekstensi.

    Sebagai bagian dari penyiapan SQL Server di Windows, file ekstensi .zip Java diinstal di lokasi ini: [SQL Server install path]\MSSQL\Binn\java-lang-extension.zip. File zip ini berisi javaextension.dll.

  2. Buat Java bahasa eksternal dari 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
    

Membuat bahasa eksternal di Linux

Sebagai bagian dari penyiapan, file ekstensi .tar.gz disimpan di bawah jalur berikut: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz.

Untuk membuat java bahasa eksternal, jalankan pernyataan T-SQL berikut di 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

Izin untuk menjalankan bahasa eksternal

Untuk menjalankan kode Java, pengguna perlu diberikan eksekusi skrip eksternal pada bahasa tertentu tersebut.

Untuk informasi selengkapnya, lihat MEMBUAT BAHASA EKSTERNAL.

Membuat pustaka eksternal

Gunakan CREATE EXTERNAL LIBRARY untuk membuat pustaka eksternal untuk file Anda .jar . SQL Server memiliki akses ke .jar file dan Anda tidak perlu mengatur izin khusus ke classpath.

Dalam sampel ini, Anda membuat dua pustaka eksternal. Satu untuk SDK dan satu untuk kode Java RegEx.

  1. File mssql-java-lang-extension.jar jar SDK diinstal sebagai bagian dari SQL Server 2019 (15.x) dan versi yang lebih baru, pada Windows dan Linux.

    • Jalur penginstalan default di Windows: <instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar

    • Jalur penginstalan default di Linux: /opt/mssql/lib/mssql-java-lang-extension.jar

    Kode ini juga sumber terbuka d dan dapat ditemukan di repositori GitHub Ekstensi Bahasa SQL Server. Untuk informasi selengkapnya, lihat Microsoft Extensibility SDK untuk Java untuk SQL Server.

  2. Buat pustaka eksternal untuk SDK.

    CREATE EXTERNAL LIBRARY sdk
    FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar')
    WITH (LANGUAGE = 'Java');
    GO
    
  3. Buat pustaka eksternal untuk kode RegEx.

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

Mengatur izin

Catatan

Lewati langkah ini, jika Anda menggunakan pustaka eksternal di langkah sebelumnya. Cara yang disarankan adalah membuat pustaka eksternal dari file Anda .jar .

Jika Anda tidak ingin menggunakan pustaka eksternal, Anda perlu mengatur izin yang diperlukan. Eksekusi skrip hanya berhasil jika identitas proses memiliki akses ke kode Anda. Anda dapat menemukan informasi selengkapnya tentang mengatur izin di panduan penginstalan.

Di Linux

Berikan izin baca/jalankan pada classpath kepada mssql_satellite pengguna.

Di Windows

Berikan izin 'Baca dan Jalankan' ke SQLRUserGroup dan SID Semua paket aplikasi pada folder yang berisi kode Java yang dikompilasi.

Seluruh pohon harus memiliki izin, dari induk akar ke sub folder terakhir.

  1. Klik kanan folder (misalnya, C:\myJavaCode) dan pilih Keamanan Properti>.
  2. Pilih Edit.
  3. Pilih Tambahkan.
  4. Di Pilih Pengguna, Komputer, Akun Layanan, atau Grup:
    1. Pilih Jenis Objek dan pastikan Prinsip keamanan bawaan dan Grup dipilih.
    2. Pilih Lokasi untuk memilih nama komputer lokal di bagian atas daftar.
  5. Masukkan SQLRUserGroup, periksa nama, dan pilih OK untuk menambahkan grup.
  6. Masukkan SEMUA PAKET APLIKASI, periksa nama, dan pilih OK untuk ditambahkan. Jika nama tidak teratasi, kunjungi kembali langkah Lokasi. SID bersifat lokal untuk komputer Anda.

Pastikan kedua identitas keamanan memiliki izin Baca dan Jalankan pada folder dan pkg sub folder.

Memanggil kelas Java

Buat prosedur tersimpan sp_execute_external_script yang memanggil untuk memanggil kode Java dari SQL Server. script Dalam parameter , tentukan yang package.class ingin Anda panggil. Dalam kode berikut, kelas milik paket yang disebut pkg dan file kelas yang disebut RegexSample.java.

Catatan

Kode tidak menentukan metode mana yang akan dipanggil. Secara default, execute metode akan dipanggil. Ini berarti Anda perlu mengikuti antarmuka SDK dan menerapkan metode eksekusi di kelas Java Anda, jika Anda ingin dapat memanggil kelas dari SQL Server.

Prosedur tersimpan mengambil kueri input (himpunan data input) dan ekspresi reguler dan mengembalikan baris yang memenuhi ekspresi reguler yang diberikan. Ini menggunakan ekspresi [Jj]ava reguler yang memeriksa apakah teks berisi kata Java atau 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

Hasil

Setelah menjalankan panggilan, Anda akan mendapatkan tataan hasil dengan dua baris.

Screenshot of Results from Java sample.

Jika Anda mendapatkan kesalahan

  • Saat Anda mengkompilasi kelas, pkg sub folder harus berisi kode yang dikompilasi untuk ketiga kelas.

  • Jika Anda tidak menggunakan pustaka eksternal, periksa izin pada setiap folder, dari root ke pkg sub folder, untuk memastikan bahwa identitas keamanan yang menjalankan proses eksternal memiliki izin untuk membaca dan menjalankan kode Anda.