Интерфейс программирования сервера

ФункцияОписание
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 должeн быть ’ ’, если значение соответствующего параметра не равно нулю, или ’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 должeн быть ’ ’, если значение соответствующего параметра не равно нулю, или ’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