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

Что такое Zulip

Zulip — программное обеспечение для реализации корпоративного чата. Разработан в 2012 году, в 2014 был…

3 месяца ago

Что такое Zookeeper

Zookeeper — cервис-координатор, который позволяет обеспечить контроль синхронизации данных. Разработан на Java компанией Apache Software…

3 месяца ago

Что такое Zimbra

Zimbra — программное обеспечение для реализации почтового сервиса или, если сказать точнее, автоматизации совместной деятельности…

3 месяца ago

Что такое Zabbix

Zabbix — бесплатная система мониторинга. Позволяет отслеживать состояние сетевых узлов, компьютеров и серверов. Возможности: Поддержка…

3 месяца ago

Что такое YouTube

YouTube — компания-владелец одноименного портала для просмотра и хранения видео. Чтобы пользоваться данным порталом достаточно…

3 месяца ago

Что такое yota

Yota — провайдер, предоставляющий доступ к сети Интернет по беспроводной связи. Впервые, сервис начал работать…

3 месяца ago