Расширения PostgreSQL: конфигурационные параметры
31 июля 2023
Расширениям PostgreSQL могут требоваться какие-то параметры конфигурации. Для решения данной задачи в PostgreSQL имеется фреймворк под названием Grand Unified Configuration. GUC используется как расширениями, так и самой системой. Давайте же разберемся, как воспользоваться GUC из расширения.
Вот простейший пример:
#include <miscadmin.h>
#include <utils/builtins.h>
#include <utils/guc.h>
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(experiment_get_message);
static char *message = NULL;
void
_PG_init(void)
{
DefineCustomStringVariable("experiment.message",
"Short description here",
NULL, /* длинное описание */
&message,
"", /* начальное значение */
PGC_USERSET,
0, /* флаги */
NULL, /* check hook */
NULL, /* assign hook */
NULL); /* show hook */
/* Запрещаем регистрацию параметров с префиксом experiment */
MarkGUCPrefixReserved("experiment");
}
Datum
experiment_get_message(PG_FUNCTION_ARGS)
{
PG_RETURN_TEXT_P(cstring_to_text(message));
}
Это весь код расширения. Если вы пропустили мой рассказ про _PG_init()
, ознакомьтесь с постом Расширения PostgreSQL: разделяемая память и локи.
Как видите, здесь все достаточно просто. Ядро системы предоставляет ряд функций с именами DefineCustomXXXVariable()
для регистрации параметров конфигурации разных типов. Поддерживаются строки, числа, булевы значения и enum’ы. Подробности можно найти в guc.h и guc.c.
Код не должен вызывать особых вопросов, кроме, быть может, PGC_USERSET
. Это значение типа GucContext. Оно определяет, кто и когда может менять параметр конфигурации. Например, если установить его в PGC_POSTMASTER
, то параметр можно будет задавать только при старте СУБД. Попытка изменить значение командой SET
, ALTER DATABASE
или ALTER SYSTEM
завершится ошибкой:
Приведенный код использует PGC_USERSET
. Это значит, что значение может менять кто угодно и когда угодно, в том числе, обычный пользователь в рамках своей сессии.
При тестировании кода с помощью TAP-тестов есть небольшой нюанс. Следует учитывать, что каждый вызов $node->safe_psql
происходит в отдельной сессии. В связи с этим, код теста должен выглядеть как-то так:
$result = $node->safe_psql("postgres", qq{
SET experiment.message TO 'abc';
SELECT experiment_get_message();
});
ok($result eq "abc", 'SET has an effect');
# ...
Отдельные вызовы $node->safe_psql
не приведут к желаемому результату.
Больше примеров вы найдете в расширениях из каталога contrib/
. Например, в уже знакомом нам pg_stat_statements.c. В файле worker_spi.c показано, как можно узнать об изменении параметров из бэкграунд воркера.
Внимательный читатель мог заметить, что также поддерживаются хуки: check hook, assign hook и show hook. На практике они используются редко. Даже такое большое расширение как TimescaleDB в своем коде использует лишь пару хуков. И то, исключительно для того, чтобы предупредить пользователя о странных сочетаниях параметров. В связи с этим в данном посте хуки мы изучать не будем.
Исчерпывающие подробности описаны в соответствующем README. Но в 99% случаев достаточно информации, представленной выше.
Полная версия исходников к этому посту доступна на GitHub.
Метки: C/C++, PostgreSQL, СУБД.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.