Categories: PostgreSQL

postgresql-add-function/

При разработке пача для PostgreSQL иногда требуется добавить новую функцию, чтобы ее можно было вызывать из SQL. Недавно вопрос о том, как это делается, задали мне два разных человека в течение одной недели. И хотя это простая задача, информация, по всей видимости, является востребованной. Давайте же рассмотрим решение.

Рассматривать будем на примере конкретного пача 260a1f18 , добавляющего в ядро функции to_bin() и to_oct() :

=# SELECT to_bin(123);
to_bin
———
1111011

=# SELECT to_bin(255);
to_bin
———-
11111111

=# SELECT pg_typeof(to_bin(255));
pg_typeof
————
text

Добавление функции осуществляется путем редактирования файла pg_proc.dat.

Например:

{ oid => ‘9030’, descr => ‘convert int4 number to binary’,
proname => ‘to_bin’, prorettype => ‘text’, proargtypes => ‘int4’,
prosrc => ‘to_bin32’ },

Если функция имеет несколько аргументов ( proargtypes ), их типы указываются через пробел. Можно определить несколько функций с одинаковыми именами ( proname ), но разными аргументами или их количеством. Само собой разумеется, реализации функции на языке C при этом будут иметь разные имена ( prosrc ). Перегрузки функций по возвращаемому значению ( prorettype ) в PostgreSQL не предусмотренно. Описание функции ( descr ) — это то, что будет показываться в выводе df+ to_bin .

Для поиска свободного Oid есть специальный скрипт:

$ ./src/include/catalog/unused_oids

6312 — 8402
8404 — 9029
9034 — 9999
Patches should use a more-or-less consecutive range of OIDs.
Best practice is to start with a random choice in the range 8000-9999.
Suggested random unused OID: 9223 (777 consecutive OID(s) available ⏎
starting here)

Еще одно важное свойство функции — это volatility . Оно указывается при помощи параметра provolatile . Значение s говорит, что функция является STABLE . Для одних и тех же аргументов функция возвращает один и тот же результат в рамках одного SQL-выражения . Это поведение функций, к примеру, зависящих от параметров конфигурации (GUCs) . Значение v соответствует VOLATILE функциям. Это «грязные» функции в том смысле, что они могут иметь внутреннее состояние, ходить в файлы или сеть, и так далее. Если provolatile не указан, то функция является IMMUTABLE . Это как чистые функции в функциональном программировании . Их возвращаемое значение зависит только от аргументов.

Но есть нюансы. Например, функция, работающая с часовыми поясами при прочих равных считается IMMUTABLE . Несмотря на то, что обновление базы часовых поясов повлияет на возвращаемые ею значения, а также будет требовать перестройки индексов, если они использовали эту функцию. Также поведение IMMUTABLE функции может измениться при обновлении самого PostgreSQL. Например, если реализация содержала ошибку.

Не считая редактирования pg_proc.dat, написание новой функции ничем не отличается от написания новой функции для расширения — см один , два , три и далее по ссылкам. Конкретная реализация to_bin32() может быть найдена в файле varlena.c:

static inline text *
convert_to_base ( uint64 value , int base )
{
const char * digits = «0123456789abcdef» ;
char buf [ sizeof ( uint64 ) * BITS_PER_BYTE ] ;
char * const end = buf + sizeof ( buf ) ;
char * ptr = end ;

Assert ( base > 1 ) ;
Assert ( base <= 16 ) ;

do
{
*— ptr = digits [ value % base ] ;
value /= base ;
} while ( ptr > buf && value ) ;

return cstring_to_text_with_len ( ptr , end ptr ) ;
}

Datum
to_bin32 ( PG_FUNCTION_ARGS )
{
uint64 value = ( uint32 ) PG_GETARG_INT32 ( 0 ) ;

PG_RETURN_TEXT_P ( convert_to_base ( value , 2 ) ) ;
}

Помимо кода функции еще нужно добавить документацию и тесты. Это уже дело техники, а конкретные изменения могут быть найдены во все том же 260a1f18 . Поэтому не будем задерживаться на этом вопросе.

Напоследок хочется отметить два момента. Во-первых, некоторые функции имеет смысл добавлять не в ядро системы, а поместить в отдельное расширение — либо стороннее, либо идущее вместе с PostgreSQL и живущее в каталоге /contrib/ . Во-вторых, pg_proc.dat является удобной точкой входа для изучения внутренностей PostgreSQL. Также файл бывает полезен, когда вы примерно понимаете, какую функцию ищите, но не знаете ее название.

admin

Share
Published by
admin

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

1 месяц ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

1 месяц ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

1 месяц ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

1 месяц ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

1 месяц ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

1 месяц ago