Создание InterBase UDF на Delphi для Linux

Posted by on in Blogs

Тема для этого поста была подсказана вопросами пользователей, которые интересовались, можно ли создавать UDF для СУБД InterBase в Delphi 10.2. Вместе с ведущим экспертом по InterBase Дмитрием Кузьменко, мы решили выяснить детали этого и составить рекомендации для наших пользователей.

Популярная реляционная СУБД Embarcadero InterBase имеет ограниченное число встроенных функций для использования в SQL-запросах, однако с самых первых версий отличалась наличием возможности у пользователей создавать двоичные модули, загружать их на сервер и применять содержащиеся в них функции в точности, как "родные" из поставки InterBase. Пользователи имеют возможность реализовывать функции, выполняющие нужную им обработку данных в соответствии с необходимой логикой любой изощренной сложности и переносить эту обработку непосредственно на центральный сервер БД - упрощая управление и администрирование таких функций и обеспечивая максимально возможное быстродействие в условиях одновременной работы множества клиентов. До появления Delphi 10.2 код UDF можно было писать на Delphi только для платформ Windows, на Linux-сервера (наиболее часто используемые в реальной работе) приходилось писать UDF на языке C.

В этой статье мы рассмотрим процесс создания UDF для InterBase 2017 на платформах Linux (64 бит) и Windows 64 с помощью Delphi 10.2 Tokyo – проверим, как передаются и возвращаются параметры, и рассмотрим некоторые особенности компиляции и переноса модулей на сервер. Это критически важно для успешного одновременного использования UDF многими пользователями. Здесь я воспользовался примерами Д.Кузьменко из статьи  "Правила написания thread-safe UDF" с этого же сайта. 

Подробная документация и руководство по написанию UDF (на английском языке) содержится в Embarcadro docwiki.

Мы выполняли тестирование на основе несколько устаревшей, но зато простой и понятной статьи "Как научиться писать UDF на Delphi за 21 минуту?" с сайта iBase.ru, где также приведены отличия для создания UDF для СУБД Firebird.

Итак, приступим!

Если у вас еще нет Linux-стенда для разработки и тестирования Linux-приложений, ознакомьтесь с предыдущими статьями:

Я использовал VirtualBox VM с Ubuntu 16.04 server, на которую был установлен InterBase 2017. Для удобства переноса модулей в Ubuntu я пользуюсь утилитой WinSCP и PuTTY-терминалом для SSH-соединения с Linux. Перенос модулей я выполнял вручную, поэтому PAServer не запускался.

Запускаем Delphi IDE. Для простейшей UDF можно создать проект 'Dynamic DLL' Я воспользовался исходным текстом примера из первой статьи, в котором имеется демо-функция ADD_A(var i1: integer; var i2: integer): integer; которая складывает числовые первый и второй параметры, возвращая их сумму.

Обратите внимание на необходимые атрибуты cdecl; export; для этой функции, а также секцию exports в конце модуля.

На картинке Target Platforms активной является Win64 - так я проверял практическую работоспособность этой UDF в Windows InterBase-сервере для разработчиков, который бесплатно поставляется вместе с Delphi или RAD Studio. Все, что требуется сделать, чтобы скомпилировать модуль для Linux, это изменить активную target-платформу на 64-bit Linux, и выполнить Build - сборку двоичного модуля. Обратите внимание, что в IDE Project Manager имя выходного файла автоматически сменилось с simpleudf.dll на libsimpleudf.so.

Теперь нужно создать внутри сервера InterBase описание, чтобы он "знал", как обращаться с этой функцией и откуда ее вызывать.

Для создания и выполнения DDL-скрипта из среды Windows на моем рабочем ПК я воспользовался RapidSQL - интерактивным инструментом разработки для баз данных из набора DB Tools, который входит в состав редакции RAD Studio Architect, но можно использовать стандартную IBConsole или другие средства соединения с InterBase.

 

Если сервер InterBase еще не был запущен в Linux, надо воспользоваться окном терминала Linux и запустить сервер:

Подключившись к серверу InterBase по IP-адресу виртуальной машины к базе данных Employee.gdb, я выполнил приведенный на картинке выше DDL-скрипт. Следует убедиться, что точка входа (имя функции) UDF написана в точности, как в исходном модуле, который был скомпилирован, а MODULE_NAME в точности равен имени выходного файла, но без расширения .so . В данном случае функция возвращает результат по значению, что указано в  строке

RETURNS integer BY VALUE

Скрипт должен успешно выполниться даже несмотря на то, что созданный двоичный модуль еще отсутствует на Linux-сервере. InterBase обращается к этому модулю только в момент вызова функции в запросе.

Настало время для переноса модуля UDF на Linux-сервер. Для этого я воспользовался WinSCP - удобной и безопасной утилитой для обмена файлами между  Windows и Linux.

Собранный в Windows выходной файл libsimpleudf.so находится в каталоге с вашим Delphi-проектом (или подкаталоге Linux64).

Стандартно, сервер InterBase устанавливается на Linux в каталог /opt/interbase. В этом случае все двоичные файлы динамических библиотек UDF нужно помещать в каталог /opt/interbase/UDF

Я также изменил права доступа к этому модулю, дав всем права на его исполнение.

Перезапустим сервер Interbase из окна терминала 

[email protected]:~$ sudo /opt/interbase/bin/ibmgr -shut -password *******
server shutdown completed
[email protected]:~$ sudo /opt/interbase/bin/ibmgr -start
server has been successfully started
[email protected]:~$

Чтобы проверить работоспособность UDF достаточно выполнить SQL запрос  

и увидеть корректный результат сложения 10+120 =  130

Итак, простейший вариант Delphi UDF отличным образом собирается и исполняется в среде Linux, а результат возвращается по значению.  Для успеха всего лишь потребовалось указать Linux64 вместо Windows как target-платформу - остальное Delphi делает автоматически. Однако, необходимо обеспечить четкое соответствие имен в исходном коде и DDL-описаниях.

А если требуется более сложный вариант возврата результата, например строкового значения? 

Об этом я расскажу в следующем посте.



About
Gold User, Rank: 11, Points: 295
SC at Embarcadero. DB Tools expert Delphi practitioner

Comments

Check out more tips and tricks in this development video: