SPI_execute#

SPI_execute

SPI_execute

SPI_execute — выполнить команду

Синтаксис

int SPI_execute(const char * command, bool read_only, long count)

Описание

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 меньше 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 (только указатель, а не содержимое структуры). Если вам нужен доступ к результатам таблицы SPI_execute или другой функции выполнения запроса в последующих вызовах, сохраните эти две глобальные переменные в локальные переменные функции на языке C.