Руководство. Поиск строки с помощью регулярных выражений (regex) в Java
Область применения: SQL Server 2019 (15.x) и более поздних версий
В этом руководстве показано, как использовать расширения языка SQL Server и создать класс Java, принимающий два столбца (идентификатор и текст) из SQL Server и регулярное выражение (regex) в качестве входного параметра. Класс возвращает в SQL Server два столбца (идентификатор и текст).
Для заданного текста в текстовом столбце, отправленном в класс Java, код проверяет, выполнено ли данное регулярное выражение, и возвращает этот текст вместе с исходным идентификатором.
В этом примере кода используется регулярное выражение, которое проверяет, содержит ли текст слово Java
или java
.
Необходимые компоненты
ядро СУБД экземпляре SQL Server 2019 (15.x) и более поздних версиях с расширением расширяемости и расширением программирования Java в Windows или Linux. Дополнительные сведения см. в разделе "Расширения языка SQL Server". Дополнительные сведения о требованиях к написанию кода см. в статье о вызове среды выполнения Java в расширениях языка SQL Server.
SQL Server Management Studio или Azure Data Studio для выполнения T-SQL.
Пакет SDK для Java SE (JDK) 8 или JRE 8 в Windows или Linux.
Файл
mssql-java-lang-extension.jar
из пакета SDK расширяемости Майкрософт для Java для SQL Server .
Для работы с этим руководством достаточно использовать javac
компиляцию командной строки.
Создание примера набора данных
Сначала создайте новую базу данных и заполните таблицу testdata
ID
столбцами.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
Создание основного класса
На этом шаге создайте файл класса с именем RegexSample.java
и скопируйте следующий код Java в этот файл.
Этот основной класс импортирует пакет SDK — это значит, что JAR-файл, скачанный в шаге 1, должен быть доступен для обнаружения из этого класса.
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-файла
Упакуйте классы и зависимости в файлы .jar
. Большинство IDE Java (например, Eclipse или IntelliJ) поддерживают создание файлов .jar
при сборке или компиляции проекта. Присвойте файлу .jar
regex.jar
имя.
Если вы не используете интегрированную среду разработки Java, можно создать .jar
файл вручную. Дополнительные сведения см. в статье "Создание файла java .jar из файлов классов".
Примечание.
В этом учебнике используются пакеты. Строка package pkg;
в верхней части класса гарантирует, что скомпилированный код сохраняется в вложенной папке pkg
. Если используется IDE, скомпилированный код автоматически сохраняется в этой папке. Если вы используете javac
для ручной компиляции классов, необходимо поместить скомпилированный код в папку pkg
.
Создание внешнего языка
Необходимо создать внешний язык в базе данных. Внешний язык — это объект области базы данных. Это значит, что внешние языки, такие как Java, необходимо создавать для каждой базы данных, в которой вы хотите их использовать.
Создание внешнего языка в Windows
Если вы используете Windows, выполните следующие действия, чтобы создать внешний язык для Java.
Создайте ZIP-файл, содержащий расширение.
В рамках установки SQL Server в Windows файл расширения
.zip
Java устанавливается в этом расположении:[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip
Этот ZIP-файл содержит файлjavaextension.dll
.Создайте внешний язык Java из 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
Создание внешнего языка в Linux
В рамках установки файл расширения .tar.gz
сохраняется по следующему пути: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz
Чтобы создать внешний язык Java, выполните в Linux следующую инструкцию T-SQL:
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
Разрешения на выполнение внешнего языка
Для выполнения кода Java пользователю необходимо предоставить разрешение на выполнение внешнего скрипта на этом языке.
Дополнительные сведения см. в разделе CREATE EXTERNAL LANGUAGE.
Создание внешних библиотек
Для создания внешней библиотеки для файлов .jar
используйте инструкцию CREATE EXTERNAL LIBRARY. SQL Server имеет доступ к .jar
файлам, и вам не нужно задавать специальные разрешения classpath
.
В этом примере вы создадите две внешние библиотеки. одна для пакета SDK, вторая для кода регулярных выражений Java.
Jar-файл
mssql-java-lang-extension.jar
пакета SDK устанавливается как часть SQL Server 2019 (15.x) и более поздних версий в Windows и Linux.Путь установки по умолчанию в Windows:
<instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar
Путь установки по умолчанию в Linux:
/opt/mssql/lib/mssql-java-lang-extension.jar
Это открытый код, который можно найти в репозитории расширений языка SQL Server в GitHub. Дополнительные сведения см. в пакете SDK расширяемости Microsoft для Java для SQL Server.
Создайте внешнюю библиотеку для пакета SDK.
CREATE EXTERNAL LIBRARY sdk FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar') WITH (LANGUAGE = 'Java'); GO
Создайте внешнюю библиотеку для кода RegEx.
CREATE EXTERNAL LIBRARY regex FROM (CONTENT = '<path>/regex.jar') WITH (LANGUAGE = 'Java'); GO
Настройка разрешений
Примечание.
Пропустите этот шаг, если на предыдущем этапе вы использовали внешние библиотеки. Рекомендуемый способ — создать внешнюю библиотеку из файла .jar
.
Если вы не хотите использовать внешние библиотеки, необходимо задать необходимые разрешения. Скрипты выполняются успешно, только если удостоверения процессов имеют доступ к вашему коду. Дополнительные сведения о настройке разрешений см. в руководстве по установке.
В Linux
Предоставьте пользователю разрешения на чтение и выполнение для пути mssql_satellite
к классу.
В Windows
Предоставьте разрешения на чтение и выполнение для SQLRUserGroup и индикаторов безопасности всех пакетов приложений в папке, содержащей скомпилированный вами код Java.
Все дерево, от корневого родительского каталога до последней вложенной папки, должно иметь разрешения.
- Щелкните папку (например,
C:\myJavaCode
) правой кнопкой мыши и выберите Свойства>Безопасность. - Выберите Изменить.
- Выберите Добавить.
- В разделе "Выбор пользователей", "Компьютер", "Учетные записи службы" или "Группы":
- Выберите типы объектов и убедитесь, что выбраны встроенные принципы безопасности и группы .
- Выберите расположения , чтобы выбрать имя локального компьютера в верхней части списка.
- Введите SQLRUserGroup, проверьте имя и нажмите кнопку "ОК ", чтобы добавить группу.
- Введите ВСЕ ПАКЕТЫ ПРИЛОЖЕНИй, проверьте имя и нажмите кнопку "ОК ", чтобы добавить. Если имя разрешить не удается, верните к шагу "Расположения". Идентификатор безопасности является локальным для вашего компьютера.
Убедитесь, что оба удостоверения безопасности имеют разрешения на чтение и выполнение в папке и вложенной папке pkg
.
Вызов класса Java
Создайте хранимую процедуру, которая вызывает sp_execute_external_script
для вызова кода Java из SQL Server. В параметре определите script
, какой package.class
вызов требуется вызвать. В следующем коде класс принадлежит пакету, вызываемому pkg
и файлу RegexSample.java
класса.
Примечание.
Код не определяет, какой метод следует вызывать. По умолчанию execute
метод будет вызываться. В связи с этим, чтобы иметь возможность вызывать класс из SQL Server, вам нужно следовать интерфейсу SDK и реализовать метод execute в классе Java.
Хранимая процедура принимает входной запрос (входной набор данных) и регулярное выражение и возвращает строки, которые выполнили данное регулярное выражение. Он использует регулярное выражение [Jj]ava
, которое проверяет, содержит ли текст слово Java
или 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
Результаты
После выполнения вызова необходимо получить результирующий набор с двумя строками.
Если возникла ошибка
При компиляции классов вложенная
pkg
папка должна содержать скомпилированный код для всех трех классов.Если вы не используете внешние библиотеки, проверьте разрешения для каждой папки из
root
pkg
под папки, чтобы убедиться, что удостоверения безопасности, выполняющие внешний процесс, имеют разрешение на чтение и выполнение кода.