Интерфейс программирования сервера
- Функции интерфейса
- SPI_connect
- SPI_finish
- SPI_execute
- SPI_exec
- SPI_execute_with_args
- SPI_prepare
- SPI_prepare_cursor
- SPI_prepare_params
- SPI_getargcount
- SPI_getargtypeid
- SPI_is_cursor_plan
- SPI_execute_plan
- SPI_execute_plan_with_paramlist
- SPI_execp
- SPI_cursor_open
- SPI_cursor_open_with_args
- SPI_cursor_open_with_paramlist
- SPI_cursor_find
- SPI_cursor_fetch
- SPI_cursor_move
- SPI_scroll_cursor_fetch
- SPI_scroll_cursor_move
- SPI_cursor_close
- SPI_keepplan
- SPI_saveplan
- SPI_register_relation
- SPI_unregister_relation
- SPI_register_trigger_data
- Вспомогательные функции интерфейса
- Управление памятью
- Управление транзакциями
- Видимость изменений данных
- Примеры
Интерфейс программирования сервера (Server Programming Interface, SPI) дает разработчикам пользовательских функций на C или RUST возможность запускать команды SQL внутри своих функций или процедур. SPI — это набор функций интерфейса, упрощающих доступ к анализатору, планировщику и исполнителю. Также SPI осуществляет управление памятью.
Примечание
Доступные процедурные языки предоставляют различные средства для выполнения команд SQL из функций. Большинство этих средств основаны на SPI, поэтому эта документация может быть полезна и для пользователей этих языков.
Обратите внимание, что если команда, вызванная через SPI, завершится с ошибкой, управление не вернется в вашу функцию на C/RUST. Скорее всего, транзакция или субтранзакция, в которой выполняется ваша функция C/RUST, откатится. (Это может показаться удивительным, учитывая, что у большинства функций SPI имеются документированные соглашения о возврате ошибок. Однако эти соглашения применяются только к ошибкам, обнаруженным в самих функциях SPI). Можно восстановить управление после ошибки, создав собственную субтранзакцию, окружающую вызовы SPI, в которых может быть ошибка.
В случае успеха функции SPI возвращают неотрицательный результат (либо
через возвращаемое целочисленное значение, либо через глобальную
переменную SPI_result
, как описано ниже). В случае ошибки будет
возвращен отрицательный результат или NULL.
Файлы исходного кода, использующие SPI, должны включать заголовочный файл executor/spi.h.
Функции интерфейса
SPI_connect — подключить функцию на C/RUST к менеджеру SPI
SPI_finish — выключить функцию на C/RUST от менеджера SPI
SPI_execute — выполнить команду
SPI_exec — Выполнить команду чтения/записи
SPI_execute_with_args — выполнить команду с внешними параметрами
SPI_prepare — подготовить оператор, но пока не выполнять его
SPI_prepare_cursor — подготовить оператор, но пока не выполнять его
SPI_prepare_params — подготовить оператор, но пока не выполнять его
SPI_getargcount — вернуть количество аргументов, необходимых для оператора, подготовленного функцией SPI_prepare
SPI_getargtypeid — вернуть OID типа данных для аргумента оператора, подготовленного функцией SPI_prepare
SPI_is_cursor_plan — вернуть true, если оператор, подготовленный функцией SPI_prepare
, можно использовать с функцией SPI_cursor_open
SPI_execute_plan — выполнить оператор, подготовленный функцией SPI_prepare
SPI_execute_plan_with_paramlist — выполнить оператор, подготовленный функцией SPI_prepare
SPI_execp — выполнить оператор в режиме чтения/записи
SPI_cursor_open — установить курсор, используя оператор, созданный с помощью функции SPI_prepare
SPI_cursor_open_with_args — установить курсор, используя запрос и параметры
SPI_cursor_open_with_paramlist — установить курсор, используя параметры
SPI_cursor_find — найти существующий курсор по имени
SPI_cursor_fetch — извлечь несколько строк через курсор
SPI_cursor_move — переместить курсор
SPI_scroll_cursor_fetch — извлечь несколько строк через курсор
SPI_scroll_cursor_move — переместить курсор
SPI_cursor_close — закрыть курсор
SPI_keepplan — сохранить подготовленный оператор
SPI_saveplan — сохранить подготовленный оператор
SPI_register_relation — сделать эфемерное именованное отношение доступным по имени в запросах SPI
SPI_unregister_relation — удалить эфемерное именованное отношение из реестра
SPI_register_trigger_data — сделать эфемерные данные триггера доступными в запросах SPI
SPI_connect
SPI_connect, SPI_connect_ext — подключить функцию на C/RUST к менеджеру SPI
Синтаксис
int SPI_connect(void)
int SPI_connect_ext(int options)
Описание
SPI_connect
устанавливает подключение вызова функции на C/RUST к менеджеру SPI.
Эту функцию следует вызывать, если вы хотите выполнять команды через SPI.
Некоторые служебные SPI-функции можно вызывать из неподключенных функций на C/RUST.
SPI_connect_ext
делает то же самое, но принимает аргумент,
позволяющий передавать дополнительные флаги. В настоящее время доступны следующие
дополнительные значения:
SPI_OPT_NONATOMIC
Устанавливает подключение SPI в неатомарном режиме, то есть
разрешает использование вызовов SPI_commit
, SPI_rollback
и SPI_start_transaction
для управления транзакцией. В противном случае вызов
данных функций приведет к немедленной ошибке.
Функция SPI_connect()
равнозначна функции SPI_connect_ext(0)
.
Возвращаемое значение
SPI_OK_CONNECT
при успешном выполнении
SPI_ERROR_CONNECT
при ошибке
SPI_finish
SPI_finish — выключить функцию на C/RUST от менеджера SPI
Синтаксис
int SPI_finish (void)
Описание
SPI_finish
закрывает существующее соединение с менеджером SPI. Эту
функцию необходимо вызвать после завершения всех операций SPI, требуемых
во время текущего вызова функции на C/RUST.
Однако при прерывании транзакции с помощью elog(ERROR)
о закрытии
соединения можно не беспокоиться. В этом случае SPI очистится автоматически.
Возвращаемое значение
SPI_OK_FINISH
при корректном отключении
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
SPI_execute
SPI_execute — выполнить команду
Синтаксис
int SPI_execute(const char * command, bool read_only, long count)
Описание
SPI_execute
выполняет указанную команду SQL для получения строк в количестве, ограниченном значением count. Если параметр
read_only имеет значение true, команда должна только
читать данные, тем самым несколько снижая издержки на ее выполнение.
Эта функция может быть вызвана только из подключенной функции на C/RUST.
Если count равно нулю, то команда выполняется для всех строк, удовлетворяющих условиями запроса. Если count больше нуля, то будет получено не больше, чем count строк; выполнение остановится при достижении этого числа, почти так же, как при добавлении к запросу предложения LIMIT. Например,
SPI_execute("SELECT * FROM foo", true, 5);
получит из таблицы не более 5 строк. Обратите внимание, что такой предел действует, только когда команда действительно возвращает строки. Например,
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
вставляет все строки из bar, игнорируя параметр count. Однако запрос
SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
вставит не более 5 строк, поскольку выполнение будет остановлено после получения пятой строки, извлеченной RETURNING.
Возможна передача несколько команд в одной строке; SPI_execute
возвращает результат для команды, выполненной последней. Ограничение количества строк count
применяется к каждой команде в отдельности (даже если на самом деле будет возвращен
только последний результат). Это ограничение не применяется к скрытым
командам, сгенерированным правилами.
Когда параметр read_only имеет значение false, SPI_execute
увеличивает счетчик
команд и вычисляет новый снимок перед выполнением каждой команды в
строке. Снимок фактически не изменяется, если текущий уровень изоляции
транзакции SERIALIZABLE или REPEATABLE READ, но в режиме READ
COMMITTED обновление снимка позволяет каждой команде видеть результаты
только что зафиксированных транзакций из других сеансов. Это важно для
согласованного поведения, когда команды изменяют базу данных.
Когда параметр read_only имеет значение true, SPI_execute
не обновляет ни снимок, ни счетчик команд, и допускает в строке команды
только простые команды SELECT
. Эти команды выполняются с использованием
снимка, предварительно установленного для окружающего запроса. Этот
режим выполнения несколько быстрее, чем режим чтения/записи, из-за
устранения издержек на каждую команду. Это также позволяет
создавать действительно стабильные функции: поскольку все
последующие выполнения будут использовать один и тот же
снимок, в результатах не будет никаких изменений.
Обычно неразумно смешивать команды только для чтения и чтения/записи в одной функции с использованием SPI; это может привести к очень запутанному поведению, поскольку запросы только для чтения не будут видеть результаты каких-либо обновлений базы данных, выполненных запросами чтения/записи.
Фактическое количество строк, для которых была выполнена (последняя)
команда, возвращается в глобальной переменной SPI_processed
. Если эта
функция возвращает значение SPI_OK_SELECT
,
SPI_OK_INSERT_RETURNING
, SPI_OK_DELETE_RETURNING
или
SPI_OK_UPDATE_RETURNING
, то для доступа к строкам результата можно
воспользоваться глобальным указателем SPITupleTable *SPI_tuptable
.
Некоторые служебные команды (такие как EXPLAIN
) также
возвращают наборы строк, и SPI_tuptable
будет содержать их результат и в
этих случаях. Некоторые служебные команды (COPY
, CREATE TABLE AS
) не
возвращают набор строк, поэтому SPI_tuptable
имеет значение NULL, но
они по-прежнему возвращают количество обработанных строк в
SPI_processed
.
Структура SPITupleTable
определяется таким образом:
typedef struct
{
MemoryContext tuptabcxt; /* контекст таблицы результатов в памяти */
uint64 alloced; /* количество зарезервированных в памяти значений */
uint64 free; /* количество свободных значений */
TupleDesc tupdesc; /* дескриптор строки */
HeapTuple *vals; /* строки */
} SPITupleTable;
vals — это массив указателей на строки. (Количество допустимых записей
задается SPI_processed
.)
tupdesc — это дескриптор строки, который можно передать функциям SPI, работающим со строками.
tuptabcxt, alloced и free являются внутренними полями, не предназначенными для
использования процедурами, вызывающими SPI.
SPI_finish
освобождает все SPITupleTable
, выделенные для текущей функции на C/RUST.
Вы можете досрочно освободить конкретную результирующую таблицу,
если закончили с ней работать, вызвав SPI_freetuptable
.
Аргументы
const char * command
строка, содержащая команду для выполнения
bool read_only
true для режима выполнения «только чтение»
long count
максимальное количество строк, которые нужно вернуть, или 0, если ограничений нет
Возвращаемое значение
Если выполнение команды было успешным, то будет возвращено одно из следующих (неотрицательных) значений:
SPI_OK_SELECT
если была выполнена команда SELECT
(но не SELECT INTO
)
SPI_OK_SELINTO
если была выполнена команда SELECT INTO
SPI_OK_INSERT
если была выполнена команда INSERT
SPI_OK_DELETE
если была выполнена команда DELETE
SPI_OK_UPDATE
если была выполнена команда UPDATE
SPI_OK_INSERT_RETURNING
если была выполнена команда INSERT RETURNING
SPI_OK_DELETE_RETURNING
если была выполнена команда DELETE RETURNING
SPI_OK_UPDATE_RETURNING
если была выполнена команда UPDATE RETURNING
SPI_OK_UTILITY
если была выполнена служебная команда (например, CREATE TABLE
)
SPI_OK_REWRITTEN
если команда была преобразована правилом в команду другого вида (например, UPDATE
стала INSERT
).
При ошибке возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
если command равен NULL или count меньше 0
SPI_ERROR_COPY
при попытке выполнить COPY TO stdout
или COPY FROM stdin
SPI_ERROR_TRANSACTION
при попытке выполнить команду управления транзакцией ( BEGIN
, COMMIT
, ROLLBACK
, SAVEPOINT
, PREPARE TRANSACTION
, COMMIT PREPARED
, ROLLBACK PREPARED
или любой их вариант)
SPI_ERROR_OPUNKNOWN
если тип команды неизвестен (такого происходить не должно)
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
Примечания
Все функции SPI, выполняющие запросы, устанавливают значения как SPI_processed
, так и
SPI_tuptable
(только указатель, а не содержимое структуры). Сохраните значения
этих двух глобальных переменных в локальные переменные функции на C/RUST, если вам
нужно получить доступ к таблице результатов выполнения SPI_execute
или другой
функции, выполняющие запросы, при последующих вызовах.
SPI_exec
SPI_exec — выполнить команду чтения/записи
Синтаксис
int SPI_exec(const char * command, long count)
Описание
SPI_exec
работает так же, как SPI_execute
, но параметр read_only
всегда принимается как false.
Аргументы
const char * command
строка, содержащая запрос для выполнения
long count
максимальное количество строк, которые нужно вернуть, или 0, если нет ограничений
Возвращаемое значение
См. описание функции SPI_execute.
SPI_execute_with_args
SPI_execute_with_args — выполнить команду с внешними параметрами
Синтаксис
int SPI_execute_with_args(const char *command,
int nargs, Oid *argtypes,
Datum *values, const char *nulls,
bool read_only, long count)
Описание
SPI_execute_with_args
выполняет команду, которая может включать
ссылки на параметры, передаваемые извне. В тексте команды параметры обозначаются символами $n,
а в вызове указываются типы данных и значения для каждого такого символа.
Параметры read_only и count имеют ту же интерпретацию, что и в SPI_execute.
Основное преимущество этой функции по сравнению с SPI_execute
состоит в том, что значения данных можно вставить в команду
без громоздких кавычек/экранирования и таким образом
сильно снизить риск атак с SQL-инъекцией.
Аналогичных результатов можно достичь, вызвав SPI_prepare, а затем
SPI_execute_plan; однако при использовании этой функции план
запроса всегда настраивается на предоставленные конкретные значения параметров. Для
одноразового выполнения запроса SPI_execute_with_args
предпочтительней. Если ту же команду нужно выполнить со
многими различными параметрами, любой из этих методов может оказаться
быстрее, в зависимости от стоимости перепланирования по сравнению с
преимуществами специализированных планов.
Аргументы
const char * command
строка с командой
int nargs
количество входных параметров ($1, $2 и т. д.)
Oid * argtypes
массив длиной nargs, содержащий OID типов данных этих параметров
Datum * values
массив длиной nargs, содержащий фактические значения параметров
const char * nulls
массив длиной nargs, описывающий, какие параметры равны NULL
Если параметр nulls равен NULL, то SPI_execute_with_args
предполагает, что ни один из параметров не содержит NULL. В противном
случае каждая запись массива nulls должна содержать ' ', если
значение соответствующего параметра не NULL, или 'n', если оно
равно NULL. (В последнем случае фактическое значение
соответствующей записи в параметре values не имеет
значения.) Обратите внимание, что nulls — это не текстовая строка,
а массив, поэтому завершающий символ '\0' не нужен.
bool read_only
true для выполнения запросов в режиме «только чтение»
long count
максимальное количество строк, которое должно быть возвращено, или 0, если нет ограничений
Возвращаемое значение
Возвращаемое значение такое же, как и для SPI_execute.
При успешном вызове переменные SPI_processed
и SPI_tuptable
устанавливаются так же, как в SPI_execute
.
SPI_prepare
SPI_prepare — подготовить оператор, пока не выполняя его
Синтаксис
SPIPlanPtr SPI_prepare(const char * command, int nargs, Oid * argtypes)
Описание
SPI_prepare
создает и возвращает подготовленный оператор для указанной
команды, но не выполняет ее. Впоследствии подготовленный оператор может
быть выполнен многократно с использованием SPI_execute_plan.
Когда одна и та же или схожая команда должна выполняться многократно,
обычно выгодно провести синтаксический анализ только один раз и
еще более выгодным может быть повторное использование плана выполнения
команды. SPI_prepare
преобразует строку команды в подготовленный
оператор, который инкапсулирует результаты синтаксического анализа.
Подготовленный оператор также предоставляет место для кэширования плана
выполнения, если выясняется, что создание специализированного плана для
каждого выполнения бесполезно.
Подготовленную команду можно обобщить, записав параметры ($1, $2 и т. д.) вместо значений, задаваемых константами в обычной команде. Тогда фактические значения параметров будут указываться при вызове SPI_execute_plan. Это позволяет использовать подготовленную команду в более широком диапазоне ситуаций, чем это было бы возможно без параметров.
Оператор, возвращаемый SPI_prepare
, может использоваться только в
текущем вызове функции на C/RUST, поскольку SPI_finish освобождает память,
выделенную для такого оператора. Но этот оператор можно сохранить на
потом, используя функции SPI_keepplan или SPI_saveplan.
Аргументы
const char * command
строка команды
int nargs
количество входных параметров ($1, $2 и т. д.)
Oid * argtypes
указатель на массив, содержащий OID типов данных параметров
Возвращаемое значение
SPI_prepare
возвращает ненулевой указатель на SPIPlan
, который
является скрытой структурой, представляющей подготовленный
оператор. В случае ошибки будет возвращен NULL, а переменная SPI_result
будет содержать один из тех же кодов ошибок, которые используются
SPI_execute, за исключением того, что код SPI_ERROR_ARGUMENT
устанавливается, если command равен NULL, или nargs меньше 0,
или nargs больше 0, а argtypes равен NULL.
Примечания
Если параметры не определены, общий план будет создан при первом
использовании SPI_execute_plan, и он же будет использоваться для всех
последующих выполнений. Если есть параметры, первые несколько
использований SPI_execute_plan
создадут специализированные планы,
которые будут специфическими для предоставленных значений параметров.
После достаточного использования одного и того же подготовленного
оператора SPI_execute_plan
построит общий план, и, если тот не намного
дороже, чем специализированные планы, начнет использовать его, вместо того
чтобы каждый раз создавать новый. Если это поведение по умолчанию не
подходит, его можно изменить, передав флаг
CURSOR_OPT_GENERIC_PLAN
или CURSOR_OPT_CUSTOM_PLAN
в
SPI_prepare_cursor, чтобы принудительно использовать общие или
специализированные планы соответственно.
Хотя основной смысл подготовленного оператора заключается в том, чтобы избежать повторного анализа и планирования оператора, QHB будет принудительно повторять анализ и планирование оператора перед его использованием в случаях, если с момента предыдущего использования подготовленного оператора изменяются определения (DDL) объектов базы данных, используемых в этом операторе. Кроме того, если значение параметра search_path изменяется от одного использования к следующему, оператор будет повторно проанализирован с использованием нового значения search_path. Дополнительную информацию о поведении подготовленных операторов см. в описании команды PREPARE.
Эта функция должна вызываться только из подключенной функции на C/RUST.
SPIPlanPtr
объявлен как указатель на скрытый тип структуры в spi.h
.
Неразумно пытаться получить доступ к его содержимому напрямую, так как
это повышает вероятность того, что ваш код сломается в будущих версиях
QHB.
Имя SPIPlanPtr
в некотором смысле сохранено по историческим причинам,
поскольку теперь структуре данных не обязательно содержать план выполнения.
SPI_prepare_cursor
SPI_prepare_cursor — подготовить оператор, пока не выполняя его
Синтаксис
SPIPlanPtr SPI_prepare_cursor(const char * command, int nargs,
Oid * argtypes, int cursorOptions)
Описание
Функция SPI_prepare_cursor
идентична SPI_prepare, но
позволяет дополнительно передать планировщику «параметры
курсора». Это битовая маска, имеющая значения, перечисленные в
nodes/parsenodes.h
для поля options структуры DeclareCursorStmt
.
SPI_prepare
всегда принимает параметры курсора равными нулю.
Аргументы
const char * command
строка команды
int nargs
количество входных параметров ($1, $2 и т. д.)
Oid * argtypes
указатель на массив, содержащий OID типов данных параметров
int cursorOptions
целочисленная битовая маска параметров курсора; ноль — поведение по умолчанию
Возвращаемое значение
SPI_prepare_cursor
имеет те же соглашения о возврате, что и
SPI_prepare.
Примечания
Полезные биты для установки в cursorOptions включают:
- CURSOR_OPT_SCROLL;
- CURSOR_OPT_NO_SCROLL;
- CURSOR_OPT_FAST_PLAN;
- CURSOR_OPT_GENERIC_PLAN;
- CURSOR_OPT_CUSTOM_PLAN.
В частности, следует отметить, что CURSOR_OPT_HOLD игнорируется.
SPI_prepare_params
SPI_prepare_params — подготовить оператор, пока не выполняя его
Синтаксис
SPIPlanPtr SPI_prepare_params(const char * command,
ParserSetupHook parserSetup,
void * parserSetupArg,
int cursorOptions)
Описание
SPI_prepare_params
создает и возвращает подготовленный оператор для
указанной команды, но не выполняет его. Эта функция равнозначна
SPI_prepare_cursor, но дополнительно позволяет вызывающему ее
задать функции обработки синтаксического анализа для управления
разбором ссылок на внешние параметры.
Аргументы
const char * command
строка команды
ParserSetupHook parserSetup
функция настройки обработчиков синтаксического анализа
void * parserSetupArg
сквозной аргумент для parserSetup
int cursorOptions
целочисленная битовая маска параметров курсора; ноль — поведение по умолчанию
Возвращаемое значение
SPI_prepare_params
имеет те же соглашения о возврате, что и
SPI_prepare.
SPI_getargcount
SPI_getargcount — вернуть количество аргументов, необходимых оператору, подготовленному функцией SPI_prepare
Синтаксис
int SPI_getargcount(SPIPlanPtr plan)
Описание
SPI_getargcount
возвращает количество аргументов, необходимых для
выполнения оператора, подготовленного функцией SPI_prepare.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
Возвращаемое значение
Количество ожидаемых аргументов для параметра plan. Если plan равен NULL или
недействителен, в SPI_result
устанавливается код SPI_ERROR_ARGUMENT, и
функция возвращает -1.
SPI_getargtypeid
SPI_getargtypeid — вернуть OID типа данных для аргумента оператора, подготовленного функцией SPI_prepare
Синтаксис
Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
Описание
SPI_getargtypeid
возвращает OID, представляющий типа аргумента с индексом argIndex
для оператора, подготовленного функцией SPI_prepare. Нумерация аргументов начинается с нуля.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
int argIndex
индекс аргумента, начиная с нуля
Возвращаемое значение
OID типа аргумента с заданным индексом. Если значение параметра plan неверное или равно NULL,
либо значение argIndex меньше 0 или больше или равно количеству аргументов,
объявленных для параметра plan, в SPI_result
устанавливается код
SPI_ERROR_ARGUMENT и возвращается InvalidOid.
SPI_is_cursor_plan
SPI_is_cursor_plan — вернуть true, если оператор, подготовленный функцией SPI_prepare
, можно использовать с функцией SPI_cursor_open
Синтаксис
bool SPI_is_cursor_plan(SPIPlanPtr plan)
Описание
SPI_is_cursor_plan
возвращает true, если оператор, подготовленный
функцией SPI_prepare, можно передать в качестве аргумента функции
SPI_cursor_open, либо false, если это не так. Для true
в параметре plan должна быть представлена только одна команда, и эта команда должна возвращать кортежи вызывающей стороне. Например, команда SELECT
подходит, если не содержит предложение INTO, а
команда UPDATE
— только если содержит предложение RETURNING.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
Возвращаемое значение
Значение true или false, указывающее, может ли plan создать
курсор, при SPI_result
равном нулю. Если определить ответ невозможно
(например, если значение plan неверное или NULL, или при вызове
без подключения к SPI), тогда в SPI_result
устанавливается
подходящий код ошибки и возвращается значение false.
SPI_execute_plan
SPI_execute_plan — выполнить оператор, подготовленный SPI_prepare
Синтаксис
int SPI_execute_plan(SPIPlanPtr plan, Datum * values, const char * nulls,
bool read_only, long count)
Описание
SPI_execute_plan
выполняет оператор, подготовленный функцией SPI_prepare или
родственными ей. Параметры read_only и count имеют то же
назначение, что и в SPI_execute.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
Datum * values
Массив фактических значений параметров. Должен иметь ту же длину, что и количество аргументов оператора.
const char * nulls
Массив, описывающий, какие параметры содержат NULL. Должен иметь ту же длину, что и количество аргументов оператора.
Если параметр nulls равен NULL, то SPI_execute_plan
предполагает, что ни
один из параметров не равен NULL. В противном случае каждая
запись массива nulls должна содержать ' ', если значение соответствующего параметра не NULL, или 'n', если оно
равно NULL. (В последнем случае фактическое значение в
соответствующем элементе values не имеет значения.) Обратите внимание,
что nulls — это не текстовая строка, а массив, поэтому завершающий символ '\0' не нужен.
bool read_only
true для выполнения запроса в режиме «только чтение»
long count
максимальное количество строк, которые нужно вернуть, или 0, если нет ограничений
Возвращаемое значение
Возвращаемое значение такое же, как и для SPI_execute, со следующими дополнительными вариантами ошибочных (отрицательных) результатов:
SPI_ERROR_ARGUMENT
если параметр plan неверен или равен NULL, либо если параметр count меньше 0
SPI_ERROR_PARAM
если параметр values равен NULL, и plan подготовлен с другими параметрами
В случае успешного вызова переменные SPI_processed
и SPI_tuptable
устанавливаются как в SPI_execute.
SPI_execute_plan_with_paramlist
SPI_execute_plan_with_paramlist - выполнить оператор, подготовленный функцией SPI_prepare
Синтаксис
int SPI_execute_plan_with_paramlist(SPIPlanPtr plan,
ParamListInfo params,
bool read_only,
long count)
Описание
SPI_execute_plan_with_paramlist
выполняет оператор, подготовленный
функцией SPI_prepare. Эта функция равнозначна SPI_execute_plan за
исключением того, что информация о значениях параметров, передаваемых в
запрос, представляется по-другому. Представление ParamListInfo может быть
удобно для передачи значений, которые уже доступны в этом формате. Функция
также поддерживает использование динамических наборов параметров
посредством функций-обработчиков, указанных в ParamListInfo.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
ParamListInfo params
структура данных, содержащая типы и значения параметров; NULL, если параметров нет
bool read_only
true для выполнения запроса в режиме «только чтение»
long count
максимальное количество строк, которые нужно вернуть, или 0, если нет ограничений
Возвращаемое значение
Возвращаемое значение такое же, как у функции SPI_execute_plan.
В случае успешного вызова переменные SPI_processed
и SPI_tuptable
устанавливаются как при вызове функции SPI_execute_plan.
SPI_execp
SPI_execp — выполнить оператор в режиме чтения/записи
Синтаксис
int SPI_execp(SPIPlanPtr plan, Datum * values, const char * nulls, long count)
Описание
SPI_execp
сходна с SPI_execute_plan, но параметр read_only всегда имеет значение false.
Аргументы
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
Datum * values
Массив фактических значений параметров. Должен иметь ту же длину, что и число аргументов оператора.
const char * nulls
Массив, описывающий, какие параметры равны NULL. Должен иметь ту же длину, что и число аргументов оператора.
Если параметр nulls равен NULL, то SPI_execp
предполагает, что ни
один из параметров не содержит NULL. В противном случае каждая
запись массива nulls должна содержать ' ', если значение соответствующего параметра не NULL, или 'n', если оно
равно NULL. (В последнем случае фактическое значение в
соответствующем элементе values не имеет значения.) Обратите внимание,
что nulls — это не текстовая строка, а массив, поэтому завершающий символ '\0' не нужен.
long count
максимальное количество строк, которые нужно вернуть, или 0, если нет ограничений
Возвращаемое значение
Возвращаемое значение такое же, как у функции SPI_execute_plan.
В случае успешного вызова переменные SPI_processed
и SPI_tuptable
устанавливаются как при вызове функции SPI_execute_plan
.
SPI_cursor_open
SPI_cursor_open — открыть курсор для оператора, созданного функцией SPI_prepare
Синтаксис
Portal SPI_cursor_open(const char * name, SPIPlanPtr plan,
Datum * values, const char * nulls,
bool read_only)
Описание
SPI_cursor_open
открывает курсор (называемый внутри базы данных порталом), который
будет выполнять оператор, подготовленный функцией SPI_prepare. Параметры этой функции имеют
тот же смысл, что и соответствующие параметры SPI_execute_plan.
Использование курсора вместо непосредственного выполнения оператора имеет два преимущества. Во-первых, результирующие строки могут быть небольшими порциями, что позволяет избежать переполнения памяти при выполнении запросов, которые возвращают много строк. Во-вторых, портал может пережить текущую функцию C/RUST (фактически он может дожить до конца текущей транзакции). Возврат имени портала в код, вызывающий функцию на C/RUST, дает возможность выдавать результат в виде набора строк.
Данные переданных параметров будут скопированы в портал курсора, поэтому их можно освободить даже во время существования курсора.
Аргументы
const char * name
имя для портала или NULL, чтобы система сама выбрала имя
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
Datum * values
Массив фактических значений параметров. Должен иметь ту же длину, что и число аргументов оператора.
const char * nulls
Массив, описывающий, какие параметры равны NULL. Должен иметь ту же длину, что и число аргументов оператора.
Если параметр nulls равен NULL, то SPI_cursor_open
предполагает, что ни
один из параметров не содержит NULL. В противном случае каждый
элемент массива nulls должен содержать ' ', если значение соответствующего параметра не NULL, или 'n', если оно
равно NULL. (В последнем случае фактическое значение в
соответствующем элементе values не имеет значения.) Обратите внимание,
что nulls — это не текстовая строка, а массив, поэтому завершающий символ '\0' не нужен.
bool read_only
true для выполнения запроса в режиме «только чтение»
Возвращаемое значение
Указатель на портал, содержащий курсор. Обратите внимание, что нет
соглашения о возврате ошибок; все ошибки будут выдаваться через elog
.
SPI_cursor_open_with_args
SPI_cursor_open_with_args — открыть курсор, используя запрос и параметры
Синтаксис
Portal SPI_cursor_open_with_args(const char *name,
const char *command,
int nargs, Oid *argtypes,
Datum *values, const char *nulls,
bool read_only, int cursorOptions)
Описание
SPI_cursor_open_with_args
открывает курсор (называемый внутри базы данных порталом),
который будет выполнять указанный запрос. Большинство параметров имеют
те же значения, что и соответствующие параметры для SPI_prepare_cursor
и SPI_cursor_open.
Для одноразового выполнения запроса эту функцию следует предпочесть
последовательным вызовам SPI_prepare_cursor
и SPI_cursor_open
.
Если одну и ту же команду нужно выполнить со множеством различных
параметров, любой из этих двух способов может быть быстрее, в
зависимости от стоимости перепланирования по сравнению с преимуществами
специализированных планов.
Данные переданных параметров будут скопированы в портал курсора, поэтому их можно освободить даже во время существования курсора.
Аргументы
const char * name
имя для портала или NULL, чтобы система сама выбрала имя
const char * command
строка команды
int nargs
количество входных параметров ($1, $2 и т. д.)
Oid * argtypes
массив длиной nargs, содержащий OID типов данных параметров
Datum * values
массив длиной nargs, содержащий фактические значения параметров
const char * nulls
Массив длиной nargs, описывающий, какие параметры равны NULL.
Если параметр nulls равен NULL, то SPI_cursor_open_with_args
предполагает, что ни
один из параметров не содержит NULL. В противном случае каждый
элемент массива nulls должен содержать ' ', если значение соответствующего параметра не NULL, или 'n', если оно
равно NULL. (В последнем случае фактическое значение в
соответствующем элементе values не имеет значения.) Обратите внимание,
что nulls — это не текстовая строка, а массив, поэтому завершающий символ '\0' не нужен.
bool read_only
true для выполнения запроса в режиме «только чтение»
int cursorOptions
целочисленная битовая маска параметров курсора; ноль — поведение по умолчанию
Возвращаемое значение
Указатель на портал, содержащий курсор. Обратите внимание, что нет
соглашения о возврате ошибок; все ошибки будут выдаваться через elog
.
SPI_cursor_open_with_paramlist
SPI_cursor_open_with_paramlist — открыть курсор, используя параметры
Синтаксис
Portal SPI_cursor_open_with_paramlist(const char *name,
SPIPlanPtr plan,
ParamListInfo params,
bool read_only)
Описание
SPI_cursor_open_with_paramlist
открывает курсор (называемый внутри базы данных порталом),
который будет выполнять оператор, подготовленный функцией SPI_prepare.
Эта функция равнозначна SPI_cursor_open за исключением того, что
информация о значениях параметров, передаваемых в запрос, представлена
по-другому. Представление ParamListInfo
может быть удобным для
передачи значений, которые уже доступны в этом формате. Функция
также поддерживает динамическую подстановку параметров через
функции-обработчики, указанные в ParamListInfo.
Содержимое переданных параметров будет скопировано в портал курсора, поэтому они могут быть освобождены еще во время существования курсора.
Аргументы
const char * name
имя для портала или NULL, чтобы система сама выбрала имя
SPIPlanPtr plan
подготовленный оператор (возвращаемый функцией SPI_prepare
)
ParamListInfo params
структура данных, содержащая типы и значения параметров; NULL, если параметров нет
bool read_only
true для выполнения запроса в режиме «только чтение»
Возвращаемое значение
Указатель на портал, содержащий курсор. Обратите внимание, что нет
соглашения о возврате ошибок; все ошибки будут выдаваться через elog
.
SPI_cursor_find
SPI_cursor_find — найти существующий курсор по имени
Синтаксис
Portal SPI_cursor_find(const char * name)
Описание
SPI_cursor_find
находит существующий портал по имени. Это в первую
очередь полезно для разрешения имени курсора, возвращенного в виде
текста какой-то другой функцией.
Аргументы
const char * name
имя портала
Возвращаемое значение
Указатель на портал с заданным именем или NULL, если такой портал не найден.
SPI_cursor_fetch
SPI_cursor_fetch — извлечь несколько строк через курсор
Синтаксис
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Описание
SPI_cursor_fetch
извлекает несколько строк через курсор. Эта функция по
действию аналогична подмножеству возможностей SQL-команды FETCH
(расширенную
функциональность предоставляет функция SPI_scroll_cursor_fetch).
Аргументы
Portal portal
портал, содержащий курсор
bool forward
true для извлечения с перемещением вперед, false — в обратном направлении
long count
максимальное количество строк для извлечения
Возвращаемое значение
В случае успешного вызова переменные SPI_processed
и SPI_tuptable
устанавливаются как в SPI_execute.
Примечания
Извлечение в обратном направлении может завершиться ошибкой, если план курсора был создан без параметра CURSOR_OPT_SCROLL.
SPI_cursor_move
SPI_cursor_move — переместить курсор
Синтаксис
void SPI_cursor_move(Portal portal, bool forward, long count)
Описание
SPI_cursor_move
пропускает некоторое количество строк в курсоре. Эта функция
по действию аналогична подмножеству возможностей SQL-команды MOVE
(расширенную
функциональность предоставляет функция SPI_scroll_cursor_move).
Аргументы
Portal portal
портал, содержащий курсор
bool forward
true для перемещения вперед, false — в обратном направлении
long count
максимальное количество строк для перемещения
Примечания
Перемещение в обратном направлении может завершиться ошибкой, если план курсора был создан без параметра CURSOR_OPT_SCROLL.
SPI_scroll_cursor_fetch
SPI_scroll_cursor_fetch — извлечь несколько строк через курсор
Синтаксис
void SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction,
long count)
Описание
SPI_scroll_cursor_fetch
извлекает несколько строк через курсора. Эта функция
действует аналогично SQL-команде FETCH
.
Аргументы
Portal portal
портал, содержащий курсор
FetchDirection direction
один из вариантов: FETCH_FORWARD, FETCH_BACKWARD, FETCH_ABSOLUTE или FETCH_RELATIVE
long count
количество строк для извлечения в направлении FETCH_FORWARD или FETCH_BACKWARD; абсолютный номер строки для извлечения с вариантом FETCH_ABSOLUTE; относительный номер строки для извлечения с вариантом FETCH_RELATIVE
Возвращаемое значение
В случае успешного вызова переменные SPI_processed
и SPI_tuptable
устанавливаются как в SPI_execute.
Примечания
Подробную интерпретацию параметров direction и count см. в описании SQL-команды FETCH.
При значении параметра direction (направление извлечения), отличном от FETCH_FORWARD, функция может завершиться ошибкой, если план курсора был создан без параметра CURSOR_OPT_SCROLL.
SPI_scroll_cursor_move
SPI_scroll_cursor_move — переместить курсор
Синтаксис
void SPI_scroll_cursor_move(Portal portal, FetchDirection direction,
long count)
Описание
SPI_scroll_cursor_move
перемещает курсор на некоторое количество строк. Эта
функция действует аналогично SQL-команде MOVE
.
Аргументы
Portal portal
портал, содержащий курсор
FetchDirection direction
один из вариантов: FETCH_FORWARD, FETCH_BACKWARD, FETCH_ABSOLUTE или FETCH_RELATIVE
long count
количество строк, на которое перемещения курсор в направлении FETCH_FORWARD или FETCH_BACKWARD; абсолютный номер строки, к которой перемещается курсор, с вариантом FETCH_ABSOLUTE; относительный номер строки, к которой перемещается курсор, с вариантом FETCH_RELATIVE
Возвращаемое значение
В случае успешного вызова переменная SPI_processed
устанавливается как в SPI_execute.
Переменная SPI_tuptable
всегда равна NULL, поскольку эта функция не возвращает строк.
Примечания
Подробную интерпретацию параметров direction и count см. в описании SQL-команды FETCH.
При значении параметра direction (направление перемещения курсора), отличном от FETCH_FORWARD, функция может завершиться ошибкой, если план курсора был создан без параметра CURSOR_OPT_SCROLL.
SPI_cursor_close
SPI_cursor_close — закрыть курсор
Синтаксис
void SPI_cursor_close(Portal portal)
Описание
SPI_cursor_close
закрывает ранее созданный курсор и освобождает ресурсы, занятые
его порталом.
Все открытые курсоры автоматически закрываются в конце транзакции.
SPI_cursor_close
нужно вызывать только в случае, если есть желание
освободить ресурсы раньше.
Аргументы
Portal portal
портал, содержащий курсор
SPI_keepplan
SPI_keepplan — сохранить подготовленный оператор
Синтаксис
int SPI_keepplan(SPIPlanPtr plan)
Описание
SPI_keepplan
сохраняет переданный оператор (подготовленный функцией SPI_prepare),
чтобы его не ликвидировали ни функция SPI_finish, ни менеджер транзакций.
Это дает возможность повторно использовать подготовленные операторы
в последующих вызовах функции на C/RUST в текущем сеансе.
Аргументы
SPIPlanPtr plan
подготовленные оператор, подлежащий сохранению
Возвращаемое значение
0 в случае успеха; SPI_ERROR_ARGUMENT, если значение параметра plan неверное или равно NULL.
Примечания
Переданный оператор перемещается в постоянное хранилище посредством корректировки указателя (копирование данных не требуется). Если позже понадобится его удалить, воспользуйтесь функцией SPI_freeplan.
SPI_saveplan
SPI_saveplan — сохранить подготовленный оператор
Синтаксис
SPIPlanPtr SPI_saveplan(SPIPlanPtr plan)
Описание
SPI_saveplan
копирует переданный оператор (подготовленный функцией SPI_prepare)
в память, которая не будет освобождена ни SPI_finish, ни менеджером
транзакций, и возвращает указатель на скопированный оператор. Это дает
возможность повторно использовать подготовленные операторы при
последующих вызовах функции на C/RUST в текущем сеансе.
Аргументы
SPIPlanPtr plan
подготовленный оператор, подлежащий сохранению
Возвращаемое значение
Указатель на скопированный оператор или NULL в случае ошибки. При ошибке
SPI_result
принимает одно из следующих значений:
SPI_ERROR_ARGUMENT
если значение параметра plan неверное или равно NULL
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
Примечания
Первоначально переданный оператор не освобождается, поэтому при желании его можно
освободить вызовом функции SPI_freeplan, чтобы избежать утечки памяти до
выполнения SPI_finish
.
В большинстве случаев SPI_keepplan предпочтительнее этой функции, поскольку она дает примерно такой же результат без необходимости физического копирования структур данных подготовленного оператора.
SPI_register_relation
SPI_register_relation — сделать эфемерное именованное отношение доступным по имени в запросах SPI
Синтаксис
int SPI_register_relation(EphemeralNamedRelation enr)
Описание
SPI_register_relation
делает эфемерное именованное отношение, вместе со
связанной информацией, доступным для запросов, планируемых и выполняемых
через текущее подключение SPI.
Аргументы
EphemeralNamedRelation enr
запись эфемерного именованного отношения в реестре
Возвращаемое значение
Если выполнение команды было успешным, то будет возвращено следующее (неотрицательное) значение:
SPI_OK_REL_REGISTER
если отношение было успешно зарегистрировано по имени
При ошибке возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
если значение параметра enr или его поля name равно NULL
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
SPI_ERROR_REL_DUPLICATE
если имя, указанное в поле name параметра enr, уже зарегистрировано для этого подключения
SPI_unregister_relation
SPI_unregister_relation — удалить эфемерное именованное отношение из реестра
Синтаксис
int SPI_unregister_relation(const char * name)
Описание
SPI_unregister_relation
удаляет эфемерное именованное отношение из
реестра для текущего подключения.
Аргументы
const char * name
имя записи отношения в реестре
Возвращаемое значение
Если выполнение команды было успешным, то будет возвращено следующее (неотрицательное) значение:
SPI_OK_REL_UNREGISTER
если блок кортежей был успешно удален из реестра
При ошибке возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
если значение параметра name равно NULL
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
SPI_ERROR_REL_NOT_FOUND
если name не обнаруживается в реестре для текущего подключения
SPI_register_trigger_data
SPI_register_trigger_data — сделать эфемерные данные триггера доступными в запросах SPI
Синтаксис
int SPI_register_trigger_data(TriggerData *tdata)
Описание
SPI_register_trigger_data
делает любые эфемерный отношения, захваченные триггером,
доступными для запросов, планируемых и выполняемых через текущее подключение SPI.
В настоящее время это подразумевает таблицы переходов, захваченные триггером AFTER
,
определенным с помощью предложения REFERENCING OLD/NEW TABLE AS
. Эта функция
должна вызываться после подключения функцией-обработчиком триггера на языке программирования.
Аргументы
TriggerData * tdata
объект TriggerData
, передаваемый функции-обработчику триггера через
fcinfo->context
Возвращаемое значение
Если выполнение команды было успешным, то будет возвращено следующее (неотрицательное) значение:
SPI_OK_TD_REGISTER
если захваченные данные триггера (если таковые имеются) были успешно зарегистрированы
При ошибке возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
если значение параметра tdata равно NULL
SPI_ERROR_UNCONNECTED
при вызове из неподключенной функции на C/RUST
SPI_ERROR_REL_DUPLICATE
если имя любого переходного отношения в данных триггера уже зарегистрировано для этого подключения
Вспомогательные функции интерфейса
SPI_fname — определить имя столбца для указанного номера столбца
SPI_fnumber — определить номер столбца для указанного имени столбца
SPI_getvalue — вернуть строковое значение указанного столбца
SPI_getbinval — вернуть двоичное значение указанного столбца
SPI_gettype — вернуть имя типа данных указанного столбца
SPI_gettypeid — вернуть OID типа данных указанного столбца
SPI_getrelname — вернуть имя указанного отношения
SPI_getnspname — вернуть пространство имен указанного отношения
SPI_result_code_string — вернуть код ошибки в виде строки
Описанные здесь функции предоставляют интерфейс для извлечения информации из наборов результатов, возвращаемых SPI_execute и другими функциями SPI.
Все функции, описанные в этом разделе, могут использоваться и в подключенных, и в неподключенных функциях на C/RUST.
SPI_fname
SPI_fname — определить имя столбца для указанного номера столбца
Синтаксис
char * SPI_fname(TupleDesc rowdesc, int colnumber)
Описание
SPI_fname
возвращает копию имени столбца с указанным номером. (Когда эта копия
имени будет не нужна, ее можно освободить с помощью pfree
.)
Аргументы
TupleDesc rowdesc
описание входной строки
int colnumber
номер столбца (отсчет начинается с 1)
Возвращаемое значение
Название столбца или NULL, если значение параметра colnumber выходит за пределы допустимого диапазона.
В случае ошибки в SPI_result
устанавливается SPI_ERROR_NOATTRIBUTE.
SPI_fnumber
SPI_fnumber — определить номер столбца для указанного имени столбца
Синтаксис
int SPI_fnumber(TupleDesc rowdesc, const char * colname)
Описание
SPI_fnumber
возвращает номер столбца для столбца с указанным именем.
Если параметр colname ссылается на системный столбец (например, ctid), будет возвращен соответствующий отрицательный номер столбца. Вызывающий должен провести тщательную проверку на наличие ошибки, досконально сравнивая возвращаемое значение с SPI_ERROR_NOATTRIBUTE; проверка результата по условию «меньше или равно 0» не будет корректной, если только не нужно исключить системные столбцы.
Аргументы
TupleDesc rowdesc
описание входной строки
const char * colname
имя столбца
Возвращаемое значение
Номер столбца (начиная с 1 для пользовательских столбцов) или SPI_ERROR_NOATTRIBUTE, если столбец с указанным именем не найден.
SPI_getvalue
SPI_getvalue — вернуть строковое значение указанного столбца
Синтаксис
char * SPI_getvalue(HeapTuple row, TupleDesc rowdesc, int colnumber)
Описание
SPI_getvalue
возвращает строковое представление значения указанного столбца.
Результат возвращается в памяти, выделенной с помощью palloc
. (Когда он станет
не нужен, можно будет освободить память с помощью pfree
.)
Аргументы
HeapTuple row
входная строка, подлежащая проверке
TupleDesc rowdesc
описание входной строки
int colnumber
номер столбца (отсчет начинается с 1)
Возвращаемое значение
Значение столбца или NULL, если столбец содержит NULL, значение colnumber
выходит за пределы допустимого диапазона (в SPI_result
устанавливается
SPI_ERROR_NOATTRIBUTE) или нет доступной функции выхода (в SPI_result
устанавливается SPI_ERROR_NOOUTFUNC).
SPI_getbinval
SPI_getbinval — вернуть двоичное значение указанного столбца
Синтаксис
Datum SPI_getbinval(HeapTuple row, TupleDesc rowdesc, int colnumber,
bool * isnull)
Описание
SPI_getbinval
возвращает значение указанного столбца во внутренней
форме (как тип Datum).
Эта функция не выделяет новое пространство для данных. В случае типа данных, передаваемого по ссылке, возвращаемое значение будет указателем на переданную строку.
Аргументы
HeapTuple row
входная строка, подлежащая изучению
TupleDesc rowdesc
описание входной строки
int colnumber
номер столбца (отсчет начинается с 1)
bool * isnull
флаг для значения NULL в столбце
Возвращаемое значение
Возвращается двоичное значение столбца. Если этот столбец содержит NULL, переменной, на которую указывает параметр isnull, присваивается значение true, иначе — false.
При ошибке в SPI_result
устанавливается SPI_ERROR_NOATTRIBUTE.
SPI_gettype
SPI_gettype — вернуть имя типа данных указанного столбца
Синтаксис
char * SPI_gettype(TupleDesc rowdesc, int colnumber)
Описание
SPI_gettype
возвращает копию имени типа данных указанного столбца. (Когда копия
имени станет не нужна, можно будет освободить ее с помощью pfree
.)
Аргументы
TupleDesc rowdesc
описание входной строки
int colnumber
номер столбца (отсчет начинается с 1)
Возвращаемое значение
Имя типа данных указанного столбца или NULL при ошибке. При ошибке в SPI_result
устанавливается SPI_ERROR_NOATTRIBUTE.
SPI_gettypeid
SPI_gettypeid — вернуть OID типа данных указанного столбца
Синтаксис
Oid SPI_gettypeid(TupleDesc rowdesc, int colnumber)
Описание
SPI_gettypeid
возвращает OID типа данных указанного столбца.
Аргументы
TupleDesc rowdesc
описание входной строки
int colnumber
номер столбца (отсчет начинается с 1)
Возвращаемое значение
OID типа данных указанного столбца или InvalidOid при ошибке. При ошибке в
SPI_result
устанавливается SPI_ERROR_NOATTRIBUTE.
SPI_getrelname
SPI_getrelname — вернуть имя указанного отношения
Синтаксис
char * SPI_getrelname(Relation rel)
Описание
SPI_getrelname
возвращает копию имени указанного отношения. (Когда копия
имени станет не нужна, можно будет освободить ее с помощью pfree
.)
Аргументы
Relation rel
входное отношение
Возвращаемое значение
Имя указанного отношения.
SPI_getnspname
SPI_getnspname — вернуть пространство имен указанного отношения
Синтаксис
char * SPI_getnspname(Relation rel)
Описание
SPI_getnspname
возвращает копию имени пространства имен, которому
принадлежит указанное отношение (Relation). Другое название пространства имен — схема.
По окончании работы со значением, возвращенным этой функцией, следует освободить его с помощью pfree
.
Аргументы
Relation rel
входное отношение
Возвращаемое значение
Имя пространства имен указанного отношения.
SPI_result_code_string
SPI_result_code_string — вернуть код ошибки в виде строки
Синтаксис
const char * SPI_result_code_string(int code);
Описание
SPI_result_code_string
выдает строковое представление кода
результата, возвращенного различными функциями SPI или сохраненного в
SPI_result
.
Аргументы
int code
код результата
Возвращаемое значение
Строковое представление кода результата.
Управление памятью
SPI_palloc — выделить память в верхнем контексте исполнителя
SPI_repalloc — перераспределить память в верхнем контексте исполнителя
SPI_pfree — освободить память в верхнем контексте исполнителя
SPI_copytuple — сделать копию строки в верхнем контексте исполнителя
SPI_returntuple — подготовить кортеж к возврату в виде Datum
SPI_modifytuple — создать новую запись, заменив выбранные поля данной записи
SPI_freetuple — освободить строку, выделенную в верхнем контексте исполнителя
SPI_freetuptable — освободить набор строк, созданных SPI_execute
или подобной функцией
SPI_freeplan — освободить ранее сохраненный подготовленный оператор
QHB выделяет память в контекстах памяти, предоставляющих
удобный метод управления распределением памяти по многим различным местам и
с различным требуемым сроком жизни этой памяти.
Уничтожение контекста освобождает всю выделенную в нем память. Таким
образом, нет необходимости отслеживать отдельные объекты, чтобы избежать
утечек памяти; вместо этого достаточно управлять только относительно
небольшим количеством контекстов. palloc
и связанные функции выделяют
память из «текущего» контекста.
Функция SPI_connect создает новый контекст памяти и делает его текущим. Функция SPI_finish восстанавливает контекст, который был текущим ранее, и уничтожает контекст, созданный SPI_connect. Эти действия гарантируют, что временные выделения памяти, сделанные внутри вашей функции на C/RUST, будут освобождены при выходе из этой функции, предотвращая утечки памяти.
Однако если вашей функции на C/RUST нужно вернуть объект в выделенной
памяти (например, значение типа данных с передачей по ссылке), вы не
можете выделить эту память, используя palloc
, по крайней мере, пока вы
подключены к SPI. Если вы попытаетесь, объект будет освобожден посредством
SPI_finish, и ваша функция на C/RUST не будет работать надежно. Для решения
этой проблемы используйте SPI_palloc, чтобы выделить память для вашего
возвращаемого объекта. SPI_palloc выделяет память в «верхнем контексте
исполнителя», то есть в контексте памяти, который был текущим при вызове
SPI_connect и является абсолютно верным контекстом для значения,
возвращаемого вашей функцией на C/RUST. Некоторые другие служебные функции,
описанные в этом разделе, также возвращают объекты, созданные в
верхнем контексте исполнителя.
Когда вызывается SPI_connect, создаваемый ей частный контекст функции
на C/RUST становится текущим контекстом. Все выделения, сделанные функциями
palloc
, repalloc
или служебными функциями SPI (за исключением случаев,
описанных в этом разделе), выполняются в этом контексте. Когда функция на C/RUST
отключается от менеджера SPI (через SPI_finish), текущим контекстом снова
становится верхний контекст исполнителя, а вся память, выделенная в
контексте памяти функции на C/RUST, освобождается и больше не может быть
использована.
SPI_palloc
SPI_palloc
— выделить память в верхнем контексте исполнителя
Синтаксис
void * SPI_palloc(Size size)
Описание
SPI_palloc
выделяет память в верхнем контексте исполнителя
Эту функцию можно использовать только при подключении к SPI. В противном случае она выдает ошибку.
Аргументы
Size size
размер выделяемой памяти (в байтах)
Возвращаемое значение
указатель на новый выделенный блок памяти заданного размера
SPI_repalloc
SPI_repalloc — перераспределить память в верхнем контексте исполнителя
Синтаксис
void * SPI_repalloc(void * pointer, Size size)
Описание
SPI_repalloc
изменяет размер сегмента памяти, ранее выделенного с помощью
функции SPI_palloc.
Эта функция больше не отличается от обычного repalloc
. Она сохранена
только для обратной совместимости существующего кода.
Аргументы
void * pointer
указатель на существующее хранилище, подлежащее изменению
Size size
размер выделяемой памяти (в байтах)
Возвращаемое значение
указатель на новый блок памяти указанного размера, в который скопировано содержимое существующего блока
SPI_pfree
SPI_pfree — освободить память в верхнем контексте исполнителя
Синтаксис
void SPI_pfree(void * pointer)
Описание
SPI_pfree
освобождает память, ранее выделенную с помощью функции SPI_palloc
или SPI_repalloc.
Эта функция больше не отличается от обычного pfree
. Она сохранена
только для обратной совместимости существующего кода.
Аргументы
void * pointer
указатель на существующий блок памяти, подлежащий освобождению
SPI_copytuple
SPI_copytuple — сделать копию строки в верхнем контексте исполнителя
Синтаксис
HeapTuple SPI_copytuple(HeapTuple row)
Описание
SPI_copytuple
создает копию строки в верхнем контексте исполнителя.
Обычно это используется для возврата измененной строки из триггера. В
функции, объявленной для возврата составного типа, используйте вместо
этого SPI_returntuple.
Эту функцию можно использовать только при подключении к SPI. В
противном случае она возвращает NULL и устанавливает в SPI_result
значение
SPI_ERROR_UNCONNECTED.
Аргументы
HeapTuple row
строка, подлежащая копированию
Возвращаемое значение
скопированная строка или NULL в случае ошибки (код ошибки см. в SPI_result
)
SPI_returntuple
SPI_returntuple — подготовить кортеж к возврату в виде Datum
Синтаксис
HeapTupleHeader SPI_returntuple(HeapTuple row, TupleDesc rowdesc)
Описание
SPI_returntuple
создает копию строки в верхнем контексте исполнителя,
возвращая ее в виде типа Datum. Перед возвратом полученный указатель нужно лишь
преобразовать в Datum посредством функции PointerGetDatum
.
Эту функцию можно использовать только при подключении к SPI. В
противном случае она возвращает NULL и устанавливает в SPI_result
значение
SPI_ERROR_UNCONNECTED.
Обратите внимание, что данный метод следует использовать для функций, которые объявлены для возврата составных типов. Для триггеров он не применяется; чтобы вернуть измененную строку в триггере, используйте функцию SPI_copytuple.
Аргументы
HeapTuple row
строка, подлежащая копированию
TupleDesc rowdesc
дескриптор для строки (передавайте каждый раз один и тот же дескриптор для наиболее эффективного кэширования)
Возвращаемое значение
HeapTupleHeader
, указывающий на скопированную строку, или NULL при ошибке
(код ошибки см. в SPI_result
)
SPI_modifytuple
SPI_modifytuple — создать строку, заменив выбранные поля исходной строки
Синтаксис
HeapTuple SPI_modifytuple(Relation rel, HeapTuple row, int ncols,
int * colnum, Datum * values, const char * nulls)
Описание
SPI_modifytuple
создает новую строку, подставляя новые значения для
выбранных столбцов и копируя остальные столбцы исходной строки. Входная строка
не изменяется. Новая строка возвращается в верхнем контексте исполнителя.
Эту функцию можно использовать только при подключении к SPI. В
противном случае она возвращает NULL и устанавливает в SPI_result
значение
SPI_ERROR_UNCONNECTED.
Аргументы
Relation rel
Используется только как источник дескриптора строки. (Передача отношения вместо дескриптора строки является ошибкой.)
HeapTuple row
строка, подлежащая изменению
int ncols
количество столбцов, подлежащих изменению
int * colnum
массив длиной ncols, содержащий номера столбцов, подлежащих изменению (номера столбцов начинаются с 1)
Datum * values
массив длиной ncols, содержащий новые значения для указанных столбцов
const char * nulls
массив длиной ncols, описывающий, какие из новых значений равны NULL
Если параметр nulls равен NULL, то SPI_modifytuple
предполагает, что
ни одно новое значение не равно NULL. В противном случае каждый элемент массива
nulls должен содержать ' ', если соответствующее новое значение не
равно NULL, или 'n', если равно. (В последнем случае фактическое значение в
соответствующем элементе values не имеет значения.) Обратите внимание,
что nulls — это не текстовая строка, а массив, поэтому завершающий символ '\0' не нужен.
Возвращаемое значение
новая строка с изменениями, размещенная в верхнем контексте исполнителя
или NULL при ошибке (код ошибки см. в SPI_result
)
В случае ошибки в SPI_result
устанавливаются следующие значения:
SPI_ERROR_ARGUMENT
если rel равен NULL, или row равен NULL, или ncols меньше или равен 0, или colnum равен NULL, или values равен NULL.
SPI_ERROR_NOATTRIBUTE
если параметр colnum содержит недопустимый номер столбца (меньше или равен 0 или больше, чем количество столбцов в параметре row)
SPI_ERROR_UNCONNECTED
если SPI неактивен
SPI_freetuple
SPI_freetuple — освободить строку, выделенную в верхнем контексте исполнителя
Синтаксис
void SPI_freetuple(HeapTuple row)
Описание
SPI_freetuple
освобождает строку, ранее выделенную в верхнем контексте
исполнителя.
Эта функция больше не отличается от обычной heap_freetuple
. Она сохранена
только для обратной совместимости существующего кода.
Аргументы
HeapTuple row
строка, подлежащая освобождению
SPI_freetuptable
SPI_freetuptable — освободить набор строк, созданный SPI_execute
или подобной функцией
Синтаксис
void SPI_freetuptable(SPITupleTable * tuptable)
Описание
SPI_freetuptable
освобождает набор строк, созданный предыдущим вызовом функции
SPI, выполняющей команды, например SPI_execute. Поэтому данная функция
часто вызывается с глобальной переменной SPI_tuptable
в качестве аргумента.
Эта функция полезна, если функция на C/RUST, использующая SPI, должна выполнять несколько команд и не хочет сохранять результаты предыдущих команд до завершения. Обратите внимание, что все наборы строк будут в любом случае освобождены при вызове SPI_finish. Кроме того, если субтранзакция запускается, а затем прерывается в ходе выполнения использующей SPI функции на C/RUST, то SPI автоматически освобождает все наборы строк, созданные в рамках субтранзакции.
Аргументы
SPITupleTable * tuptable
указатель на набор строк, подлежащий освобождению, или NULL, если ничего не делать не нужно
SPI_freeplan
SPI_freeplan — освободить ранее сохраненный подготовленный оператор
Синтаксис
int SPI_freeplan(SPIPlanPtr plan)
Описание
SPI_freeplan
освобождает подготовленный оператор, ранее возвращенный функцией
SPI_prepare или сохраненный функцией SPI_keepplan или SPI_saveplan.
Аргументы
SPIPlanPtr plan
указатель на оператор, подлежащий освобождению
Возвращаемое значение
0 в случае успеха; SPI_ERROR_ARGUMENT, если значение параметра plan неверно или равно NULL.
Управление транзакциями
SPI_commit — зафиксировать текущую транзакцию
SPI_rollback — прервать текущую транзакцию
SPI_start_transaction — начать новую транзакцию
Невозможно выполнить команды управления транзакциями, например COMMIT
и
ROLLBACK
через функции SPI, такие как SPI_execute. Однако существуют
отдельные функции интерфейса, позволяющие управлять транзакциями через SPI.
Обычно небезопасно и нецелесообразно запускать и завершать транзакции в
произвольных пользовательских функциях, вызываемых из SQL, без учета
контекста, в котором они вызываются. Например, граница транзакции в
середине функции, которая является частью сложного SQL-выражения, являющегося
частью какой-либо другой команды SQL, скорее всего приведет к непонятным
внутренним ошибкам или сбоям. Представленные здесь функции интерфейса
предназначены, в первую очередь, для использования реализациями процедурных
языков в целях поддержки управления транзакциями в процедурах уровня SQL,
которые вызываются командой CALL
(с учетом контекста ее вызова). Процедуры,
реализованные на C/RUST и использующие SPI, могут реализовывать ту же логику, но
подробное освещение этой темы этого выходит за рамки данной документации.
SPI_commit
SPI_commit, SPI_commit_and_chain — зафиксировать текущую транзакцию
Синтаксис
void SPI_commit(void)
void SPI_commit_and_chain(void)
Описание
SPI_commit
фиксирует текущую транзакцию. Это примерно равнозначно
выполнению SQL-команды COMMIT
. После фиксации транзакции и перед выполнением
дальнейший действий с базой данных нужно запустить новую транзакцию с помощью
функции SPI_start_transaction.
SPI_commit_and_chain
делает то же самое, но новая транзакция немедленно
запускается с теми же характеристиками, что и только что завершенная, как при
выполнении SQL-команды COMMIT AND CHAIN
.
Эти функции можно выполнить, только если SPI-подключение было установлено в неатомарном режиме путем вызова функции SPI_connect_ext.
SPI_rollback
SPI\rollback, SPI_rollback_and_chain — отменить текущую транзакцию
Синтаксис
void SPI_rollback(void)
void SPI_rollback_and_chain(void)
Описание
SPI_rollback
откатывает текущую транзакцию. Это примерно равнозначно
выполнению SQL-команды ROLLBACK
. После отката транзакции и перед выполнением
дальнейший действий с базой данных нужно запустить новую транзакцию с помощью
функции SPI_start_transaction.
SPI_rollback_and_chain
делает то же самое, но новая транзакция немедленно
запускается с теми же характеристиками, что и только что завершенная, как при
выполнении SQL-команды ROLLBACK AND CHAIN
.
Эти функции можно выполнить, только если SPI-подключение было установлено в неатомарном режиме путем вызова функции SPI_connect_ext.
SPI_start_transaction
SPI_start_transaction — начать новую транзакцию
Синтаксис
void SPI_start_transaction(void)
Описание
SPI_start_transaction
начинает новую транзакцию. Эту функцию можно вызвать
только после SPI_commit или SPI_rollback, поскольку в этот момент
транзакция не активна. Обычно, когда вызывается процедура, использующая
SPI, уже существует активная транзакция, поэтому попытка начать еще одну до
закрытия текущей приведет к ошибке.
Эту функцию можно выполнить, только если SPI-подключение было установлено в неатомарном режиме путем вызова функции SPI_connect_ext.
Видимость изменений данных
Следующие правила регулируют видимость изменений данных в функциях, использующих SPI (или любых других функциях на C/RUST):
- Во время выполнения команды SQL любые изменения данных, сделанные этой командой, невидимы для самой команды. Например, в:
INSERT INTO a SELECT * FROM a;
вставленные строки невидимы для части SELECT
.
-
Изменения, произведенные командой В, видны всем командам, которые запускаются после нее, независимо от того, были ли эти команды запущены внутри В (во время ее выполнения) или после завершения В.
-
Команды, выполняемые через SPI внутри функции, вызванной командой SQL (обычной функцией или триггером), следуют одному или другому из приведенных выше правил в зависимости от флага чтения/записи, передаваемого в SPI. Команды, выполняемые в режиме «только чтение», следуют первому правилу: они не могут видеть изменения, произведенные вызывающей командой. Команды, выполняемые в режиме «чтение-запись», следуют второму правилу: они могут видеть все произведенные к этому моменту изменения.
-
Все стандартные процедурные языки устанавливают режим SPI «чтение-запись» в зависимости от атрибута изменчивости функции. Команды функций STABLE и IMMUTABLE выполняются в режиме «только чтение», тогда как команды функций VOLATILE выполняются в режиме «чтение-запись». Хотя авторы функций на C/RUST могут нарушить это соглашение, вряд ли это будет хорошей идеей.
Следующий раздел содержит пример, который иллюстрирует применение этих правил.
Примеры
Этот раздел содержит очень простой пример использования SPI. Функция на C/RUST
execq
принимает команду SQL в качестве первого аргумента и число строк в
качестве второго, выполняет команду с помощью функции SPI_exec и возвращает
количество строк, обработанных командой. Вы можете найти более сложные
примеры для SPI в дереве исходного кода в src/test/regress/regress.c.
#include "postgres.h"
#include "executor/spi.h"
#include "utils/builtins.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(execq);
Datum
execq(PG_FUNCTION_ARGS)
{
char *command;
int cnt;
int ret;
uint64 proc;
/* Преобразовать данный текстовый объект в строку C */
command = text_to_cstring(PG_GETARG_TEXT_PP(0));
cnt = PG_GETARG_INT32(1);
SPI_connect();
ret = SPI_exec(command, cnt);
proc = SPI_processed;
/*
* Если были извлечены какие-то строки, вывести их через elog(INFO).
*/
if (ret > 0 && SPI_tuptable != NULL)
{
TupleDesc tupdesc = SPI_tuptable->tupdesc;
SPITupleTable *tuptable = SPI_tuptable;
char buf[8192];
uint64 j;
for (j = 0; j < proc; j++)
{
HeapTuple tuple = tuptable->vals[j];
int i;
for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %s%s",
SPI_getvalue(tuple, tupdesc, i),
(i == tupdesc->natts) ? " " : " |");
elog(INFO, "EXECQ: %s", buf);
}
}
SPI_finish();
pfree(command);
PG_RETURN_INT64(proc);
}
Так эта функция будет объявлена после ее компиляции в разделяемую библиотеку (подробности в разделе Компиляция и связывание динамически загружаемых функций):
CREATE FUNCTION execq(text, integer) RETURNS int8
AS 'имя_файла'
LANGUAGE C STRICT;
Пример сеанса:
=> SELECT execq('CREATE TABLE a (x integer)', 0);
execq
-------
0
(1 row)
=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0));
INSERT 0 1
=> SELECT execq('SELECT * FROM a', 0);
INFO: EXECQ: 0 -- вставлено функцией execq
INFO: EXECQ: 1 -- возвращено функцией execq и вставлено верхней командой INSERT
execq
-------
2
(1 row)
=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1);
execq
-------
1
(1 row)
=> SELECT execq('SELECT * FROM a', 10);
INFO: EXECQ: 0
INFO: EXECQ: 1
INFO: EXECQ: 2 -- 0 + 2, вставлена только одна строка — как указано
execq
-------
3 -- 10 — только максимальное значение, 3 — реальное число строк
(1 row)
=> DELETE FROM a;
DELETE 3
=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
INSERT 0 1
=> SELECT * FROM a;
x
---
1 -- нет строк в a (0) + 1
(1 row)
=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
INFO: EXECQ: 1
INSERT 0 1
=> SELECT * FROM a;
x
---
1
2 -- была только одна строка в a + 1
(2 rows)
-- Этот пример демонстрирует правило видимости изменений данных:
=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a;
INFO: EXECQ: 1
INFO: EXECQ: 2
INFO: EXECQ: 1
INFO: EXECQ: 2
INFO: EXECQ: 2
INSERT 0 2
=> SELECT * FROM a;
x
---
1
2
2 -- 2 строки * 1 (x в первой строке)
6 -- 3 строки (2 + 1 только что вставленная) * 2 (x во второй строке)
(4 rows) ^^^^^^
строки, видимые в execq() при разных вызовах