Поиск по этому блогу

понедельник, 23 января 2012 г.

UDF для Firebird на Lazarus

Задача. Найти вхождение подстроки в строке.
(Эта задача (функция) реализована в составе UDF библиотеки RFunc, но она использует тип данных VARCHAR(16383) и написана на C, т.е. можно ее допилить.) 
Функция должна принимать два параметра: подстроку и строку, и возвращать целое значение - позицию подстроки.
Чтобы написать UDF для Firebird используем Lazarus.
Создаем dll. Файл - Создать - Библиотека
И используем возможности функции pos, которая возвращает позицию подстроки
Function  Pos(const substr:shortstring;const s:shortstring):SizeInt;



library fpc_str_utils;

{$mode objfpc}{$H+}

uses
  SysUtils, strings
  { you can add units after this };
// Переменные передаются by value (по значению)
// s1 - подстрока которую ищем s2 - строка в которой ищем
// результат возвращаем по значению
function fsu_pos(const s1,s2: pchar):integer; cdecl; //export;
var
  ss1,ss2: shortstring;
begin
 Result:=0;
 ss1 := strpas(s1); // преобразовать pchar в shortstring
 ss2 := strpas(s2);
 Result:=pos(ss1,ss2); // получить позицию
end;

exports
  fsu_pos  name 'fsu_pos';

begin
   isMultiThread:=True; //
end.   

Для того, чтобы FB знал о существовании библиотеки и функции необходимо запустить Sql запрос

--drop EXTERNAL FUNCTION fsu_pos; // удалить

DECLARE EXTERNAL FUNCTION fsu_pos
        cstring(254),
        cstring(254)
        RETURNS integer by value
        ENTRY_POINT 'fsu_pos' MODULE_NAME 'fpc_str_utils.dll';


При описании функции используется cdecl соглашение вызова. Т.е. аргументы передаются через стек, справа налево. Очистку стека производит вызывающая программа
еще о способах вызова Соглашения вызова

Тестируем.
Заводим табличку TEST
CREATE TABLE TEST (
    ID    INTEGER NOT NULL,
    NAME  VARCHAR(100)
);
Наполняем ее и запускаем запрос
select fsu_pos('русс',name), name from TEST
и смотрим ошибки в логах firebird.log

Ссылки по теме

Как научиться писать UDF за 21 минуту - особенности Udf при передаче параметров по ссылке (by ref), thread safe udf
Правила написания thread safe udf
Список UDF