SPI_execute — выполнить команду
int SPI_execute(const char *command, boolread_only, longcount)
SPI_execute выполняет указанную SQL-команду
для count строк. Если read_only
имеет значение true, команда должна быть только для чтения, и накладные расходы на выполнение несколько снижаются.
Эта функция может быть вызвана только из подключенной функции на языке C.
Если 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, или
SPI_OK_MERGE_RETURNING,
то для доступа к результирующим строкам можно использовать
глобальный указатель SPITupleTable *SPI_tuptable to
access the result rows. Некоторые вспомогательные команды (такие как
EXPLAIN) также возвращают наборы строк, и SPI_tuptable
в этих случаях также будет содержать результат. Некоторые вспомогательные команды
(COPY, CREATE TABLE AS) не возвращают набор строк, поэтому
SPI_tuptable имеет значение NULL, но они всё равно возвращают количество
обработанных строк в SPI_processed.
Структура SPITupleTable определена
следующим образом:
typedef struct SPITupleTable
{
/* Открытые элементы */
TupleDesc tupdesc; /* дескриптор кортежа */
HeapTuple *vals; /* массив кортежей */
uint64 numvals; /* количество допустимых кортежей */
/* Закрытые элементы, не предназначенные для внешнего использования */
uint64 alloced; /* выделенный размер массива vals */
MemoryContext tuptabcxt; /* контекст памяти результирующей таблицы */
slist_node next; /* ссылка для внутреннего учёта */
SubTransactionId subid; /* подтранзакция, в которой была создана таблица кортежей */
} SPITupleTable;
Поля tupdesc,
vals, и
numvals
могут использоваться вызывающими функциями SPI; остальные поля являются внутренними.
vals представляет собой массив указателей на строки.
Число строк задается параметром numvals
(по ряду исторических причин это количество также возвращается
в SPI_processed).
tupdesc является дескриптором строк, который можно передавать функциям SPI, работающим со строками.
SPI_finish освобождает все
SPITupleTableы, выделенные во время выполнения текущей
функции на языке C. Вы можете освободить определенную результирующую таблицу раньше, если она вам больше не нужна, вызвав функцию SPI_freetuptable.
const char * commandстрока, содержащая команду для выполнения
bool read_onlytrue для выполнения в режиме «только чтение»
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_MERGE
если MERGE была выполнена
SPI_OK_INSERT_RETURNING
если INSERT RETURNING была выполнена
SPI_OK_DELETE_RETURNING
если DELETE RETURNING была выполнена
SPI_OK_UPDATE_RETURNING
если UPDATE RETURNING была выполнена
SPI_OK_MERGE_RETURNING
если MERGE RETURNING была выполнена
SPI_OK_UTILITY
если вспомогательная команда (например, CREATE TABLE)
была выполнена
SPI_OK_REWRITTEN
если команда была переписана в команду другого типа (например,
UPDATE стал INSERT) посредством правило.
В случае ошибки возвращается одно из следующих отрицательных значений:
SPI_ERROR_ARGUMENT
если command имеет значение NULL или
count меньше 0
SPI_ERROR_COPY
если COPY TO stdout или COPY FROM stdin
была предпринята попытка
SPI_ERROR_TRANSACTION
если была предпринята попытка выполнения команды управления транзакциями
(BEGIN,
COMMIT,
ROLLBACK,
SAVEPOINT,
PREPARE TRANSACTION,
COMMIT PREPARED,
ROLLBACK PREPARED,
или любой их вариант)
SPI_ERROR_OPUNKNOWNесли тип команды неизвестен (чего не должно быть)
SPI_ERROR_UNCONNECTEDпри вызове из неподключенной функции на языке C
Все функции SPI для выполнения запросов устанавливают значения обеих
SPI_processed и
SPI_tuptable (только указатель, а не содержимое
структуры). Сохраните значения этих двух глобальных переменных в локальные переменные функции на языке C, если вам необходим доступ к таблице результатов
SPI_execute или другой функции выполнения запросов
в последующих вызовах.