Иллюстрированный самоучитель по PostgreSQL

Расширение PostgreSQL

В листинге 7.48 приведена пара очень простых функций, написанных на языке С. Первая функция, is_zero(int), возвращает true (1), если при вызове ей был передан аргумент 0; в противном случае возвращается false (0). Вторая функция, is_zero_two(int .int), возвращает true, если хотя бы один из переданных аргументов равен нулю.

Листинг 7.48. Функции на языке С.

/* is_zero.c
* Простейшие проверочные функции */
int is_zero(int);
int is_zero_two(int .int):
int is_zero(int incoming) {
/* Вернуть true, если аргумент равен 0. */
if (incoming == 0) return 1;
else return 0: }
int is_zero_two(int left, int right) {
/* Вернуть true, если хотя бы один из аргументов равен 0. */
if (left – 0 || right == 0) return 1:
else return 0; }

Внимание
В этот простейший пример не были включены заголовочные файлы PostgreSQL. В данном случае они не нужны из-за очевидного соответствия между типами данных С и SQL. Более реальные примеры с использованием внутреннего интерфейса API PostgreSQL и структур данных находятся во вложенном каталоге contrib исходного каталога PostgreSQL
.

В листинге 7.49 файл is_zero.c компилируется с ключом – shared, а полученный общий модуль создается в файле is_zero.so. Путь к файлу передается в определении функции в команде CREATE FUNCTION; атрибут LANGUAGE сообщает, что функция написана на языке С.

Листинг 7.49. Создание функции на языке С.

[jworsley@cmd ~]$ gcc – shared is_zero.c – о is_zero.so
[jworsley@cmd – ]$ psql – U manager booktown
Welcome to psql .the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
booktown-* CREATE FUNCTION is_zero(int4) RETURNS Boolean
booktown-l AS '/home/jworsley/is_zero.so' LANGUAGE 'C';
CREATE

Команда CREATE FUNCTION в листинге 7.49 создает функцию с именем is_zero(), которая получает один аргумент типа int4 и возвращает значение типа boolean. В объявление включена ссылка на функцию С с именем is_zero(int), реализованную в объектном модуле /home/jworsley/is_zero.so (поскольку в языке С нет типа boolean, PostgreSQL приходится преобразовывать целочисленное значение, возвращаемое функцией, к логическому типу). При этом число 0 преобразуется в false, a 1 – в true.

По умолчанию PostgreSQL ищет в общем модуле функцию с тем же именем, с которым она создается в PostgreSQL. Такой способ подходит для функции is_zero(integer), имя которой соответствует откомпилированному символическому имени функции is_zero(int) в файле is_zero.so. Для предотвращения конфликтов имен вторая функция в общем объектном модуле определяется с сигнатурой is_zero_two(int.int). Чтобы ассоциировать ее с перегруженной функцией PostgreSQL, получающей два аргумента вместо одного, имя функции С в виде строковой константы передастся после пути к файлу общего модуля.

Имя указывается без круглых скобок и без перечисления аргументов, а от пути к файлу оно отделяется запятой:

CREATE FUNCTION имя ([ тип_аргумента [….] ])
RETURNS тип_возвращаемого_значения
AS 'определение'. 'имя_в_объектном_файле'
LANGUAGE 'С' [ WITH (атрибут [….]) ]

В листинге 7.50 подгружается тот же общий модуль, но на этот раз перегруженная функция PostgreSQL ассоциируется с функций С is_zero_two.

Листинг 7.50. Перегрузка функции С.

booktown=# CREATE FUNCTION is_zero(int4 .int4) RETURNS Boolean
booktown-# AS '/home/jworsley/is_zero.so'. 'is_zero_two'
booktown-* LANGUAGE 'C':
CREATE
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.