Создание InterBase UDF на Delphi для LinuxИсточник: communityembarcaderocom
Тема для этого поста была подсказана вопросами пользователей, которые интересовались, можно ли создавать 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 из окна терминала asovtsov@ubuntu16srv:~$ sudo /opt/interbase/bin/ibmgr -shut -password ******* server shutdown completed asovtsov@ubuntu16srv:~$ sudo /opt/interbase/bin/ibmgr -start server has been successfully started asovtsov@ubuntu16srv:~$ Чтобы проверить работоспособность UDF достаточно выполнить SQL запрос и увидеть корректный результат сложения 10+120 = 130 Итак, простейший вариант Delphi UDF отличным образом собирается и исполняется в среде Linux, а результат возвращается по значению. Для успеха всего лишь потребовалось указать Linux64 вместо Windows как target-платформу - остальное Delphi делает автоматически. Однако, необходимо обеспечить четкое соответствие имен в исходном коде и DDL-описаниях. А если требуется более сложный вариант возврата результата, например строкового значения? Об этом я расскажу в следующем посте. |