Интерфейс программирования сервера
Функция | Описание |
---|---|
SPI_connect | Подключиться к менеджеру SPI |
SPI_finish | Отключиться от менеджера SPI |
SPI_execute | Выполнить SQL команду |
SPI_exec | Выполнить SQL команду, аналогично SPI_execute , но с параметром read_only=false |
SPI_execute_with_args | Выполнить SQL команду, аналогично SPI_execute , но позволяет передать дополнительные параметры |
SPI_prepare | Подготовить оператор, не выполняя его |
SPI_prepare_cursor | Подготовить оператор, не выполняя его, аналогично SPI_prepare , но позволяет задать направление чтения |
SPI_prepare_params | Подготовить оператор, не выполняя его, аналогично SPI_prepare_cursor , дополнительные параметры задаются через hook функцию |
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_params , аналогично SPI_execute_plan , но позволяет передать значения дополнительных параметров |
SPI_execp | Выполнить оператор, подготовленный SPI_prepare , аналогично SPI_execute_plan , но в режиме только чтения |
SPI_cursor_open | Открыть курсор для оператора, созданного с помощью SPI_prepare |
SPI_cursor_open_with_args | Открыть курсор, используя переданную команду и параметры |
SPI_cursor_open_with_paramlist | Открыть курсор, подготовленный SPI_prepare_params , используя переданные параметры |
SPI_cursor_find | Найти существующий курсор по имени |
SPI_cursor_fetch | Прочитать несколько строк из курсора (только вперед/назад относительно текущей позиции) |
SPI_cursor_move | Переместить курсор (только вперед/назад относительно текущей позиции) |
SPI_scroll_cursor_fetch | Извлечь несколько строк из курсора |
SPI_scroll_cursor_move | Переместить курсор |
SPI_cursor_close | Закрыть курсор |
SPI_keepplan | Сохранить оператор, подготовленный SPI_prepare , до конца сессии |
SPI_saveplan | Возвращает копию оператора, подготовленного SPI_prepare |
SPI_register_relation | Сделать эфемерное именованное отношение доступным по имени в запросах SPI |
SPI_unregister_relation | Удалить эфемерное именованное отношение из реестра |
SPI_register_trigger_data | Сделать доступными данные эфемерного триггера в запросах SPI |
Функция | Описание |
---|---|
SPI_fname | Определить имя столбца для указанного номера столбца |
SPI_fnumber | Определить номер столбца для указанного имени столбца |
SPI_getvalue | Вернуть строковое значение указанного столбца |
SPI_getbinval | Вернуть двоичное значение указанного столбца |
SPI_gettype | Вернуть имя типа данных указанного столбца |
SPI_gettypeid | Вернуть OID типа данных указанного столбца |
SPI_getrelname | Вернуть имя указанного отношения |
SPI_getnspname | Вернуть пространство имен указанного отношения |
SPI_result_code_string | Вернуть код ошибки в виде строки |
Функция | Описание |
---|---|
SPI_palloc | Выделить память] |
SPI_repalloc | Перераспределить память |
SPI_pfree | Освободить память |
SPI_copytuple | Сделать копию строки |
SPI_returntuple | Возвращает копию строки в качестве Datum |
SPI_modifytuple | Создает новую запись, заменив выбранные поля исходной записи |
SPI_freetuple | Освободить запись |
SPI_freetuptable | Освободить строки, прочитанные SPI_execute или подобной функцией |
SPI_freeplan | Освободить оператор, сохраненный с помощью SPI_keepplan , SPI_saveplan |
Функция | Описание |
---|---|
SPI_commit | Зафиксировать текущую транзакцию |
SPI_rollback | Отменить текущую транзакцию |
SPI_start_transaction | Начать новую транзакцию |
Интерфейс программирования сервера (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
SPI_connect
, SPI_connect_ext
- подключиться к менеджеру SPI
Синтаксис
int SPI_connect (void)
int SPI_connect_ext (int options )
Описание
SPI_connect
открывает соединение к менеджеру SPI.
Вы должны вызвать эту функцию, если хотите выполнять команды через SPI.
Некоторые служебные SPI-функции можно вызывать без открытия соединения.
SPI_connect_ext
делает то же самое, но имеет аргумент,
позволяющий передавать опциональные флаги. В настоящее время доступны следующие
значения:
SPI_OPT_NONATOMIC
- Устанавливает соединение SPI неатомарным, то есть
разрешает использование вызовов
SPI_commit
,SPI_rollback
иSPI_start
для управления. В противном случае вызов данных функций приведет к немедленной ошибке.
SPI_connect()
эквивалентно SPI_connect_ext(0)
.
Возвращаемое значение
SPI_OK_CONNECT
- при успехе
SPI_ERROR_CONNECT
- при ошибке
SPI_finish
SPI_finish
- отключиться от менеджера SPI
Синтаксис
int SPI_finish (void)
Описание
SPI_finish
закрывает существующее соединение с менеджером SPI. Вы
должны вызывать эту функцию после завершения всех операций со SPI, необходимых
во время текущего выполнения Вашей функции на C/RUST.
Вызов SPI_finish
не требуется, если транзакция прервана
с помощью elog(ERROR). В этом случае SPI очистится автоматически.
Возвращаемое значение
SPI_OK_FINISH
- корректное отключение
SPI_ERROR_UNCONNECTED
- нет открытого соединения с менеджером SPI
SPI_execute
SPI_execute
- выполнить SQL команду
Синтаксис
int SPI_execute(const char * command, bool read_only, long count)
Описание
SPI_execute
выполняет указанную команду SQL для count
строк. Если
read_only
имеет значение true, команда должна только
читать данные, а накладные расходы на выполнение несколько уменьшаются.
Эта функция может быть вызвана только после подключения к менеджеру SPI.
Если 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; /* memory context of result table */
uint64 alloced; /* number of alloced vals */
uint64 free; /* number of free vals */
TupleDesc tupdesc; /* row descriptor */
HeapTuple *vals; /* rows */
} SPITupleTable;
- vals - это массив указателей на строки. (Количество допустимых записей
задается
SPI_processed
.); - tupdesc - это дескриптор строки, который вы можете передать функциям SPI, работающим со строками;
- tuptabcxt, alloced и free являются внутренними полями, не предназначенными для использования вызывающими SPI.
SPI_finish
освобождает все SPITupleTable
, выделенные во время текущего соединения с SPI.
Вы можете освободить определенную таблицу результатов ранее,
если закончили с ней работать, вызвав 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 | если не открыто подключение к менеджеру SPI |
Примечания
Все SPI функции, выполняющие запросы, устанавливают значения переменных SPI_processed
и
SPI_tuptable
(только указатель, а не содержимое структуры). Сохраните значения
этих двух глобальных переменных в локальные переменные в Вашей функции на C/RUST, если вам
нужно получить доступ к таблице результатов выполнения SPI_execute
или другой
функции SPI_execute_xxx
при последующих вызовах.
SPI_exec
SPI_exec - выполнить SQL команду, аналогично SPI_execute
, но с параметром read_only=false
Синтаксис
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 - выполнить SQL команду, аналогично SPI_execute, но позволяет передать дополнительные параметры
Синтаксис
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
- SQL запрос
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
, может использоваться только в
текущем соединении с менеджером SPI, поскольку SPI_finish освобождает память,
выделенную для такого оператора. Но оператор можно сохранить для дальнейшего использования,
используя функции SPI_keepplan или SPI_saveplan.
Аргументы
const char * command
- SQL запрос
int nargs
- количество входных параметров ( $1, $2 и т. д.)
Oid * argtypes
- указатель на массив длинной
nargs
, содержащий 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 для получения дополнительной информации о поведении подготовленных операторов.
Эта функция должна вызываться только после подключения к менеджеру SPI.
SPIPlanPtr объявлен как указатель на непрозрачный тип структуры в spi.h
.
Неразумно пытаться получить доступ к его содержимому напрямую, так как
это повышает вероятность того, что ваш код сломается в будущих версиях
QHB.
Имя SPIPlanPtr несколько историческое, поскольку структура данных не обязательно содержит план выполнения.
SPI_prepare_cursor
SPI_prepare_cursor - подготовить оператор, не выполняя его, аналогично SPI_prepare, но позволяет задать направление чтения
Синтаксис
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
- SQL запрос
int nargs
- количество входных параметров ( $1, $2 и т. д.)
Oid * argtypes
- указатель на массив длинной
nargs
, содержащий 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
- подготовить оператор, не выполняя его, аналогично SPI_prepare_cursor, дополнительные параметры задаются через hook функцию
Синтаксис
SPIPlanPtr SPI_prepare_params(const char * command, ParserSetupHook parserSetup,
void * parserSetupArg, int cursorOptions)
Описание
SPI_prepare_params
создает и возвращает подготовленный оператор для
указанного запроса, но не выполняет его. Эта функция эквивалентна
SPI_prepare_cursor, за исключением того, что вызывающая сторона
может передать hook функцию для контроля за разбором
ссылок на внешние параметры.
Аргументы
const char * command
- SQL запрос
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
Возвращаемое значение
Если SPI_result
содержит 0, тогда true
или false
указывает,
может ли plan
создать курсор или нет. Если невозможно определить ответ
(например, если 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
-
Массив, описывающий, какие параметры являются нулевыми. Должен иметь ту же длину, что и число аргументов оператора.
-
Если указатель
nulls
равен NULL, тогдаSPI_execute_plan
предполагает, что ни один из параметров не является нулевым. В противном случае каждый элемент массиваnulls
должен быть ’ ’, если значение соответствующего параметра не равно нулю, или ’n’, если значение соответствующего параметра равно нулю. (В последнем случае фактическое значение в соответствующем элементе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_params, аналогично SPI_execute_plan, но позволяет передать значения дополнительных параметров.
Синтаксис
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
может быть
удобна для передачи значений, которые уже доступны в этом формате. Функция
также поддерживает динамическую подстановку параметров через
hook
функции, указанные в 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
- выполнить оператор, подготовленный SPI_prepare, аналогично SPI_execute_plan, но в режиме только чтения
Синтаксис
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
-
Массив, описывающий, какие параметры являются нулевыми. Должен иметь ту же длину, что и число аргументов оператора.
-
Если указатель
nulls
равен NULL, тогдаSPI_execp
предполагает, что ни один из параметров не является нулевым. В противном случае каждый элемент массиваnulls
должeн быть ’ ’, если значение соответствующего параметра не равно нулю, или ’n’, если значение соответствующего параметра равно нулю. (В последнем случае фактическое значение в соответствующем элементе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
-
Массив, описывающий, какие параметры являются нулевыми. Должен иметь ту же длину, что и число аргументов оператора.
-
Если указатель
nulls
равен NULL, тогдаSPI_cursor_open
предполагает, что ни один из параметров не является нулевым. В противном случае каждый элемент массиваnulls
должeн быть ’ ’, если значение соответствующего параметра не равно нулю, или ’n’, если значение соответствующего параметра равно нулю. (В последнем случае фактическое значение в соответствующем элементе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
- SQL запрос
int nargs
- количество входных параметров ( $1, $2 и т. д.)
Oid * argtypes
- массив длинной
nargs
, содержащий OID-ы типов данных входных параметров
Datum * values
- массив длинной
nargs
, содержащий фактические значения параметров
const char * nulls
-
массив длинной
nargs
, описывающий, какие параметры равны NULL -
Если указатель
nulls
равен NULL, тогдаSPI_cursor_open_with_args
предполагает, что ни один из параметров не является нулевым. В противном случае каждый элемент массиваnulls
должен быть ’ ’, если значение соответствующего параметра не равно нулю, или ’n’, если значение соответствующего параметра равно нулю. (В последнем случае фактическое значение в соответствующем элементеvalues
не имеет значения.) Обратите внимание, что nulls - это не текстовая строка, а массив, поэтому завершающий символ ’\0’ не нужен.
bool read_only
- true для выполнения запроса только читающего данные
int cursorOptions
- целочисленная битовая маска параметров курсора; ноль - поведение по умолчанию
Возвращаемое значение
Указатель на портал, содержащий курсор. Обратите внимание, что нет
соглашения о возврате ошибок; любая ошибка будет записана через elog
.
SPI_cursor_open_with_paramlist
SPI_cursor_open_with_paramlist
- открыть курсор, подготовленный SPI_prepare_params, используя переданные параметры
Синтаксис
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
может быть
удобна для передачи значений, которые уже доступны в этом формате. Функция
также поддерживает динамическую подстановку параметров через
hook
функции, указанные в 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
- количество строк для извлечения, если параметр
direction
равенFETCH_FORWARD
илиFETCH_BACKWARD
- абсолютный номер строки для извлечения, если параметр
direction
равенFETCH_ABSOLUTE
- относительный номер строки для извлечения, если параметр
direction
равенFETCH_RELATIVE
Возвращаемое значение
В случае успешного завершения SPI_processed
и SPI_tuptable
устанавливаются как в SPI_execute.
Примечания
См. SQL команду FETCH для получения подробной информации об
интерпретации параметров direction
и count
.
Если параметр 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
- количество строк для перемещения, если параметр
direction
равенFETCH_FORWARD
илиFETCH_BACKWARD
- абсолютный номер строки для перемещения, если параметр
direction
равенFETCH_ABSOLUTE
- относительный номер строки для извлечения, если параметр
direction
равенFETCH_RELATIVE
Возвращаемое значение
В случае успешного завершения SPI_processed
устанавливаются как в SPI_execute.
SPI_tuptable
всегда устанавливается в NULL, поскольку эта функция не возвращает строк.
Примечания
См. SQL команду FETCH для получения подробной информации об
интерпретации параметров direction
и count
.
Если параметр 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
- сохранить оператор, подготовленный SPI_prepare
, до конца сессии
Синтаксис
int SPI_keepplan(SPIPlanPtr plan)
Описание
SPI_keepplan
сохраняет переданный оператор (подготовленный SPI_prepare
), чтобы он не был освобожден ни SPI_finish, ни менеджером транзакций.
Это дает Вам возможность повторно использовать подготовленные операторы
в последующих вызовах Вашей функции на C/RUST в текущей сессии.
Аргументы
SPIPlanPtr plan
- оператор, подготовленный вызовом SPI_prepare
Возвращаемое значение
0 в случае успеха; SPI_ERROR_ARGUMENT
если параметр plan
равен NULL или
недействителен
Примечания
Переданный оператор перемещается в постоянное хранилище с помощью копирования указателя (копирование данных не требуется). Если позже Вы захотите удалить его, используйте для этого SPI_freeplan.
SPI_saveplan
SPI_saveplan
- возвращает копию оператора, подготовленного SPI_prepare
Синтаксис
SPIPlanPtr SPI_saveplan(SPIPlanPtr plan)
Описание
SPI_saveplan
копирует переданный оператор (подготовленный SPI_prepare
) в память, которая не будет освобождена ни SPI_finish, ни менеджером
транзакций, и возвращает указатель на скопированный оператор. Это дает
Вам возможность повторно использовать подготовленные операторы в
последующих вызовах Вашей функции на C/RUST в текущей сессии.
Аргументы
SPIPlanPtr plan
- оператор, подготовленный вызовом SPI_prepare
Возвращаемое значение
Указатель на скопированный оператор; или NULL случае неудачи. В
случае ошибки SPI_result
устанавливается следующим образом:
SPI_ERROR_ARGUMENT
- если параметр
plan
равен NULL или недействителен
SPI_ERROR_UNCONNECTED
- если не открыто подключение к менеджеру SPI
Примечания
Первоначально переданный оператор не освобождается, поэтому вы можете освободить его вручную вызовом 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
равен NULL или его полеname
равно NULL
SPI_ERROR_UNCONNECTED
- если не открыто подключение к менеджеру SPI
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
- если не открыто подключение к менеджеру SPI
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. В настоящее время это
обозначает таблицы переходов (transition relations), захваченные триггером AFTER определенным
с помощью предложения REFERENCING OLD/NEW TABLE AS. Эта функция
должна вызываться обработчиком PL триггера после подключения.
Аргументы
TriggerData * tdata
- объект
TriggerData
передается в функцию-обработчик триггера черезfcinfo->context
Возвращаемое значение
Если выполнение команды было успешным, то будет возвращено следующее (неотрицательное) значение:
SPI_OK_TD_REGISTER
- если захваченные данные триггера (если такие есть) успешно зарегистрированы
При ошибке возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
- если параметр
tdata
равен NULL
SPI_ERROR_UNCONNECTED
- если не открыто подключение к менеджеру SPI
SPI_ERROR_REL_DUPLICATE
- если имя какого-либо временного отношения в данных триггера уже зарегистрировано для этого соединения
Функции поддержки интерфейса
Описанные здесь функции предоставляют интерфейс для извлечения информации из наборов результатов, возвращаемых SPI_execute и другими функциями SPI.
Все функции, описанные в этом разделе, могут использоваться с подключением и без подключения к менеджеру SPI.
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
- флаг для нулевого значения в столбце
Возвращаемое значение
Двоичное значение столбца. Переменная, на которую указывает
параметр 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
возвращает копию имени пространства имен (схемы), которому
принадлежит указанное отношение. Вы
можете использовать 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
- код результата
Возвращаемое значение
Строковое представление кода результата.
Управление памятью
QHB выделяет память в контекстах памяти, предоставляющих
удобный метод управления распределениями, осуществляемыми во многих
разных местах, которые должны жить в различное количество времени.
Уничтожение контекста освобождает всю память, выделенную в нем. Таким
образом, нет необходимости отслеживать отдельные объекты, чтобы избежать
утечек памяти; вместо этого достаточно управлять только относительно
небольшим количеством контекстов. palloc
и связанные функции выделяют
память из «текущего» контекста.
SPI_connect создает новый контекст памяти и делает его текущим. SPI_finish восстанавливает предыдущий текущий контекст памяти и уничтожает контекст, созданный SPI_connect. Эти действия гарантируют, что временные выделения памяти, сделанные внутри вашей функции на C/RUST, будут освобождены при выходе из функции на C/RUST, избегая утечки памяти.
Однако, если вашей функции на C/RUST необходимо вернуть объект в выделенной
памяти (например, значение типа данных с передачей по ссылке), вы не
можете выделить эту память, используя palloc
, по крайней мере, пока вы
подключены к SPI. Если вы попытаетесь, объект будет освобожден с помощью
SPI_finish, и ваша функция на C/RUST не будет работать надежно. Чтобы решить
эту проблему, используйте SPI_palloc для выделения памяти для вашего
возвращаемого объекта. SPI_palloc выделяет память в «контексте вышестоящего
исполнителя», то есть в контексте памяти, который был текущим при
SPI_connect, что является точно правильным контекстом для значения,
возвращаемого вашей функцией на C/RUST. Некоторые из других служебных функций,
описанных в этом разделе, также возвращают объекты, созданные в
контексте вышестоящего исполнителя.
Когда вызывается SPI_connect, частный контекст функции C/RUST, создаваемый
SPI_connect, становится текущим контекстом. Все выделения сделанные
функциями 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_returntuple
нельзя применять для
триггеров; используйте 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
, описывающий, какие новые значения равны нулю -
Если параметр
nulls
равен NULL тогдаSPI_modifytuple
предполагает, что новые значения не равны NULL. В противном случае каждая запись массива nulls должна быть ’ ’, если соответствующее новое значение не равно нулю, или ’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. Кроме того, если субтранзакция запускается и затем прерывается при выполнении функции C/RUST, использующей SPI, 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 или
недействителен.
Управление транзакциями
Невозможно выполнить команды управления транзакциями, такие как COMMIT и ROLLBACK через функции SPI, такие как SPI_execute. Однако существуют отдельные интерфейсные функции, позволяющие управлять транзакциями через SPI.
Обычно небезопасно и нецелесообразно запускать и завершать транзакции в произвольных пользовательских функциях, вызываемых из SQL, без учета контекста, в котором они вызываются. Например, граница транзакции в середине функции, которая является частью сложного SQL выражения, являющегося частью какой-либо другой SQL команды, вероятно, приведет к неясным внутренним ошибкам или сбоям. Представленные здесь интерфейсные функции предназначены, в первую очередь, для использования в реализациях на процедурных языках для поддержки управления транзакциями в процедурах уровня SQL, которые вызываются командой CALL, с учетом контекста вызова 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.
-
Изменения, сделанные командой "C", видны всем командам, которые запускаются после "C", независимо от того, запущены ли они внутри "C" (во время выполнения "C") или после того, как "C" выполнена.
-
Изменения, выполненные через SPI внутри функции, вызванной командой SQL (обычной функцией или триггером), следуют одному или другому из приведенных выше правил в зависимости от флага чтения / записи, передаваемого в SPI. Команды, выполняемые в режиме только для чтения, следуют первому правилу: они не могут видеть изменения вызывающей команды. Команды, выполняемые в режиме чтения-записи, следуют второму правилу: они могут видеть все сделанные изменения.
-
Все стандартные процедурные языки устанавливают режим чтения-записи SPI в зависимости от атрибута волатильности функции. Команды функций STABLE и IMMUTABLE выполняются в режиме только для чтения, в то время как команды функций VOLATILE выполняются в режиме чтения-записи. Хотя авторы функций на C/RUST могут нарушать это соглашение, вряд ли это будет хорошей идеей.
Следующий раздел содержит пример, который иллюстрирует применение этих правил.
Примеры
Этот раздел содержит очень простой пример использования SPI. Функция C execq принимает команду SQL в качестве первого аргумента и число строк в качестве второго, выполняет команду с помощью SPI_exec и возвращает количество строк, обработанных командой. Вы можете найти более сложные примеры для SPI в дереве исходного кода в src/test/regress/regress.c и в модуле spi.
#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;
/* Convert given text object to a C string */
command = text_to_cstring(PG_GETARG_TEXT_PP(0));
cnt = PG_GETARG_INT32(1);
SPI_connect();
ret = SPI_exec(command, cnt);
proc = SPI_processed;
/*
* If some rows were fetched, print them via elog(INFO).
*/
if (ret > 0 && SPI_tuptable != NULL)
{
TupleDesc tupdesc = SPI_tuptable->tupdesc;
SPITupleTable *tuptable = SPI_tuptable;
char buf[8192];ержки управления транзакциями в процедурах уровня SQL, которые вызываются командой CALL, с учетом контекста вызова CALL. Функции, реализованные на C/RUST и использующие SPI, могут реализовывать ту же логику, но подробности этого выходят за рамки данной документации.
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 'filename'
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 -- inserted by execq
INFO: EXECQ: 1 -- returned by execq and inserted by upper 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, only one row inserted - as specified
execq
-------
3 -- 10 is the max value only, 3 is the real number of rows
(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 -- no rows in 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 -- there was one row in a + 1
(2 rows)
-- This demonstrates the data changes visibility rule:
=> 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 rows * 1 (x in first row)
6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row)
(4 rows) ^^^^^^
rows visible to execq() in different invocations