SPI_execute#
SPI_execute
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
, то вы можете использовать глобальный указатель SPITupleTable *SPI_tuptable
для доступа к результатам строк. Некоторые вспомогательные команды (например, EXPLAIN
) также возвращают наборы строк, и SPI_tuptable
будет содержать результаты в этих случаях. Некоторые вспомогательные команды (COPY
, CREATE TABLE AS
) не возвращают набор строк, поэтому SPI_tuptable
равно NULL, но они все равно возвращают количество обработанных строк в SPI_processed
.
Структура SPITupleTable
определена следующим образом:
typedef struct SPITupleTable { /* Public members */ TupleDesc tupdesc; /* tuple descriptor */ HeapTuple *vals; /* array of tuples */ uint64 numvals; /* number of valid tuples */ /* Private members, not intended for external callers */ uint64 alloced; /* allocated length of vals array */ MemoryContext tuptabcxt; /* memory context of result table */ slist_node next; /* link for internal bookkeeping */ SubTransactionId subid; /* subxact in which tuptable was created */ } SPITupleTable;
Поля tupdesc
,
vals
и
numvals
могут быть использованы вызывающими SPI; остальные поля являются внутренними.
vals
- это массив указателей на строки.
Количество строк задается numvals
(по историческим причинам это количество также возвращается
в SPI_processed
).
tupdesc
- это описание строки, которое можно передать
функциям SPI, работающим с строками.
SPI_finish
освобождает все
SPITupleTable
, выделенные во время текущей
C функции. Вы можете освободить определенную таблицу результатов раньше, если вы
закончили с ней, вызвав 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_MERGE
если была выполнена команда
MERGE
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
меньше 0SPI_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
(только указатель, а не содержимое структуры). Если вам нужен доступ к результатам таблицы SPI_execute
или другой функции выполнения запроса в последующих вызовах, сохраните эти две глобальные переменные в локальные переменные функции на языке C.