SPI_execute — ejecuta un comando
int SPI_execute(const char *command, boolread_only, longcount)
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.
const char * commandcadena que contiene el comando a ejecutar
bool read_onlytrue para una ejecución de solo lectura
long count
número máximo de filas a devolver,
o 0 para ilimitado
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_OPUNKNOWNsi el tipo de comando es desconocido (no debería suceder)
SPI_ERROR_UNCONNECTEDsi se llama desde una función en C no conectada
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.