Мир InterBase

         

Создание собственных функций


Мы не будем подробно останавливаться на всех особенностях создания пользовательских функций, поскольку данный механизм достаточно прост, однако продемонстрируем написание и подключение одной функции на примере. В качестве средства разработки мы будем использовать Borland Delphi. Для примера также будет применяться стандартная база данных EMPLOYEE.GDB.

В нашем примере мы создадим функцию, которая будет преобразовывать строку к верхнему регистру. Подобная функция может оказаться полезной, если вы не задали опцию COLLATE для ваших строковых полей. Кроме того, работа со строковыми параметрами, как правило, вызывает наибольшее количество вопросов при создании пользовательских функций. Разумеется, мы исходим из предположения, что вы знакомы с принципом создания DLL при помощи Delphi.

library TestUDF;

uses SysUtils;

function malloc(Size: Integer): Pointer; cdecl; external

'msvcrt.dll';

function StrUpperCase(sz: PChar): PChar; cdecl; export;

var Tmp: string;

begin

Tmp := AnsiUpperCase(sz);

Result := malloc(length(Tmp) + 1);

StrPCopy(Result, Tmp);

end;

exports

StrUpperCase;

begin

end.

Динамическая библиотека экспортирует только одну функцию: StrUpperCase. Для передачи строковых параметров, равно как и результата функции, используется тип Pchar, т е. динамическая строка, ограниченная символами #0. Смысл кода нашей функции очевиден: мы приводим строку sz у верхнему регистру, используя стандартную функцию AnsiUpperCase. Данная функция корректно работает с русскими буквами, если в системе установлена русская кодовая страница. После этого выделяем память для результирующей переменной, используя malloc - стандартную функцию Windows. Остается только скопировать значение временной переменной Tmp в переменную Result. Скомпилируйте библиотеку и поместите полученный файл TestUDF.dll в нужный каталог. Если вы используете InterBase 6.x или его клоны, то это каталог \Udf, который находится в каталоге установки сервера. Необходимо зарегистрировать функцию в базе данных. Для регистрации необходимо выполнить команду DECLARE EXTERNAL FUNCTION, которая имеет следующий синтаксис:


DECLARE EXTERNAL FUNCTION name [datatype | CSTRING (int)

[, datatype | CSTRING (int) ...] ]

RETURNS (datatype [BY VALUE] | CSTRING (int)} [FREE_IT] 

ENTRY_POINT 'entryname' 

MODULE_NAME ' modulename';

Параметр name - это имя пользовательской функции внутри базы данных. Он не обязательно должен совпадать с реальным названием функции в DLL.

Параметр datatype определяет тип параметров. На параметры накладываются следующие ограничения:

все параметры передаются по ссылке;

выходной параметр (значение функции) может возвращаться по значению;

параметры не могут быть массивами.

Если вы хотите применять строковые параметры, то вы должны использовать тип CSTRING В скобках необходимо указать максимальную длину строки. Если строка является результатом функции, она всегда передается по ссылке, а не по значению.

Параметр FREE_IT указывает InterBase, что после выполнения функции необходимо автоматически освободить память, выделенную для параметров. Очевидно, данная опция нужна только в том случае, если наша библиотека сама мм делила память под какие-либо параметры функции.

В параметре entryname необходимо указывать название функции в DLL, ко торую мы собственно и хотим декларировать как пользовательскую функцию.

В параметре modulename необходимо указать название файла DLL, в котором находится декларируемая функция пользователя.

Стоит заметить, что параметры entryname и modulename регистрочувствительные.

Таким образом, чтобы добавить нашу функцию в базу данных, нам необходимо выполнить следующую команду:

DECLARE EXTERNAL FUNCTION USTRUPPERCASE 

cstring(254)

RETURNS cstnng(254) FREE_IT 

ENTRY_POINT 'StrUpperCase' MODULE_NAME 'TestUDF.dll'

После этого мы сможем использовать новую функцию USTRUPPERCASE в любом SQL-запросе. Например, мы можем проверить, как работает функция на следующем запросе:

SELECT USTRUPPERCASE(DEPARTMENT) FROM DEPARTMENT

Запрос вернет названия отделов из таблицы DEPARTMENT:



Рис 1.5. Результат использования UDF USTRUPPERCASE


Содержание раздела