SPI_execute

SPI_execute — ejecuta un comando

Synopsis

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

Descripción

SPI_execute ejecuta el comando SQL especificado para un número de filas dado por count. Si read_only es true, el comando debe ser de solo lectura y la sobrecarga de ejecución se reduce ligeramente.

Esta función solo se puede llamar desde una función en C conectada.

Si count es cero, entonces el comando se ejecuta para todas las filas a las que se aplica. Si count es mayor que cero, se recuperará un máximo de count filas; la ejecución se detiene cuando se alcanza dicho número, de manera similar a añadir una cláusula LIMIT a la consulta. Por ejemplo,

SPI_execute("SELECT * FROM foo", true, 5);

recuperará como máximo 5 filas de la tabla. Tenga en cuenta que dicho límite solo es efectivo cuando el comando realmente devuelve filas. Por ejemplo,

SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);

inserta todas las filas de bar, ignorando el parámetro count. Sin embargo, con

SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);

se insertarían como máximo 5 filas, ya que la ejecución se detendría después de recuperar la quinta fila del resultado RETURNING.

Puede pasar varios comandos en una sola cadena; SPI_execute devuelve el resultado del último comando ejecutado. El límite de count se aplica a cada comando por separado (aunque en realidad solo se devolverá el último resultado). El límite no se aplica a los comandos ocultos generados por reglas.

Cuando read_only es false, SPI_execute incrementa el contador de comandos y calcula una nueva instantánea (snapshot) antes de ejecutar cada comando en la cadena. La instantánea en realidad no cambia si el nivel de aislamiento de la transacción actual es SERIALIZABLE o REPEATABLE READ, pero en modo READ COMMITTED la actualización de la instantánea permite que cada comando vea los resultados de las transacciones recién confirmadas de otras sesiones. Esto es esencial para un comportamiento consistente cuando los comandos modifican la base de datos.

Cuando read_only es true, SPI_execute no actualiza ni la instantánea ni el contador de comandos, y solo permite comandos SELECT simples en la cadena de comandos. Los comandos se ejecutan utilizando la instantánea establecida previamente para la consulta circundante. Este modo de ejecución es algo más rápido que el modo de lectura/escritura debido a la eliminación de la sobrecarga por comando. También permite construir funciones genuinamente estables (stable): dado que las ejecuciones sucesivas utilizarán la misma instantánea, no habrá cambios en los resultados.

Por lo general, no es aconsejable mezclar comandos de solo lectura y de lectura-escritura dentro de una misma función utilizando SPI; esto podría resultar en un comportamiento muy confuso, ya que las consultas de solo lectura no verían los resultados de ninguna actualización de la base de datos realizada por las consultas de lectura-escritura.

El número real de filas para las cuales se ejecutó el (último) comando se devuelve en la variable global SPI_processed. Si el valor de retorno de la función es SPI_OK_SELECT, SPI_OK_INSERT_RETURNING, SPI_OK_DELETE_RETURNING, SPI_OK_UPDATE_RETURNING o SPI_OK_MERGE_RETURNING, entonces puede usar el puntero global SPITupleTable *SPI_tuptable para acceder a las filas de resultado. Algunos comandos de utilidad (como EXPLAIN) también devuelven conjuntos de filas, y SPI_tuptable contendrá el resultado también en estos casos. Algunos comandos de utilidad (COPY, CREATE TABLE AS) no devuelven un conjunto de filas, por lo que SPI_tuptable es NULL, pero siguen devolviendo el número de filas procesadas en SPI_processed.

La estructura SPITupleTable se define así:

typedef struct SPITupleTable
{
    /* Miembros públicos */
    TupleDesc   tupdesc;        /* descriptor de tupla */
    HeapTuple  *vals;           /* array de tuplas */
    uint64      numvals;        /* número de tuplas válidas */

    /* Miembros privados, no destinados a llamadores externos */
    uint64      alloced;        /* longitud asignada del array vals */
    MemoryContext tuptabcxt;    /* contexto de memoria de la tabla de resultados */
    slist_node  next;           /* enlace para contabilidad interna */
    SubTransactionId subid;     /* subxact en la que se creó tuptable */
} SPITupleTable;

Los campos tupdesc, vals y numvals pueden ser utilizados por los llamadores de SPI; los campos restantes son internos. vals es un array de punteros a filas. El número de filas está dado por numvals (por razones históricas, este recuento también se devuelve en SPI_processed). tupdesc es un descriptor de fila que puede pasar a las funciones de SPI que manejan filas.

SPI_finish libera todas las estructuras SPITupleTable asignadas durante la función en C actual. Puede liberar una tabla de resultados particular antes, si ha terminado con ella, llamando a SPI_freetuptable.

Argumentos

const char * command

cadena que contiene el comando a ejecutar

bool read_only

true para una ejecución de solo lectura

long count

número máximo de filas a devolver, o 0 para ilimitado

Valor de retorno

Si la ejecución del comando fue exitosa, entonces se devolverá uno de los siguientes valores (no negativos):

SPI_OK_SELECT

si se ejecutó un SELECT (pero no SELECT INTO)

SPI_OK_SELINTO

si se ejecutó un SELECT INTO

SPI_OK_INSERT

si se ejecutó un INSERT

SPI_OK_DELETE

si se ejecutó un DELETE

SPI_OK_UPDATE

si se ejecutó un UPDATE

SPI_OK_MERGE

si se ejecutó un MERGE

SPI_OK_INSERT_RETURNING

si se ejecutó un INSERT RETURNING

SPI_OK_DELETE_RETURNING

si se ejecutó un DELETE RETURNING

SPI_OK_UPDATE_RETURNING

si se ejecutó un UPDATE RETURNING

SPI_OK_MERGE_RETURNING

si se ejecutó un MERGE RETURNING

SPI_OK_UTILITY

si se ejecutó un comando de utilidad (por ejemplo, CREATE TABLE)

SPI_OK_REWRITTEN

si el comando fue reescrito en otro tipo de comando (por ejemplo, UPDATE se convirtió en un INSERT) por una regla (rule).

En caso de error, se devuelve uno de los siguientes valores negativos:

SPI_ERROR_ARGUMENT

si command es NULL o count es menor que 0

SPI_ERROR_COPY

si se intentó realizar COPY TO stdout o COPY FROM stdin

SPI_ERROR_TRANSACTION

si se intentó un comando de manipulación de transacciones (BEGIN, COMMIT, ROLLBACK, SAVEPOINT, PREPARE TRANSACTION, COMMIT PREPARED, ROLLBACK PREPARED o cualquier variante de estos)

SPI_ERROR_OPUNKNOWN

si el tipo de comando es desconocido (no debería suceder)

SPI_ERROR_UNCONNECTED

si se llama desde una función en C no conectada

Notas

Todas las funciones de ejecución de consultas de SPI establecen tanto SPI_processed como SPI_tuptable (solo el puntero, no el contenido de la estructura). Guarde estas dos variables globales en variables locales de la función en C si necesita acceder a la tabla de resultados de SPI_execute u otra función de ejecución de consultas en llamadas posteriores.