Documentation PostgreSQL 14.22 » Programmation serveur » Interface de programmation serveur » Fonctions d'interface » SPI_execute

Précédent | Niveau supérieur | Suivant
SPI_finish | Sommaire | SPI_exec

## SPI_execute

SPI_execute — exécute une commande

## Synopsis

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

## Description

`SPI_exec` lance la commande SQL spécifiée pour `count` lignes. Si `read_only` est `true`, la commande doit être en lecture seule et la surcharge de l'exécution est quelque peu réduite.

Cette fonction ne devrait être appelée qu'à partir d'une fonction C connectée.

Si `count` vaut zéro, alors la commande est exécutée pour toutes les lignes auxquelles elle s'applique. Si `count` est supérieur à 0, alors pas plus de `count` lignes seront récupérées. L'exécution s'arrêtera quand le compte est atteint, un peu comme l'ajout d'une clause `LIMIT` à une requête. Par exemple :

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

récupérera 5 lignes tout au plus à partir de la table. Notez qu'une telle limite n'est efficace qu'à partir du moment où la requête renvoie des lignes. Par exemple :

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

insérera toutes les lignes de `bar`, en ignorant le paramètre `count`. Cependant, avec

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

au plus cinq lignes seront insérées car l'exécution s'arrêtera après la cinquième ligne renvoyée par `RETURNING`.

Vous pourriez passer plusieurs commandes dans une chaîne. `SPI_execute` renvoie le résultat pour la dernière commande exécutée. La limite `count` s'applique à chaque commande séparément (même si seul le dernier résultat sera renvoyé). La limite n'est pas appliquée à toute commande cachée générée par les règles.

Quand `read_only` vaut `false`, `SPI_execute` incrémente le compteur de la commande et calcule une nouvelle image avant d'exécuter chaque commande dans la chaîne. L'image n'est pas réellement modifiée si le niveau d'isolation de la transaction en cours est `SERIALIZABLE` ou `REPEATABLE READ` mais, en mode `READ COMMITTED`, la mise à jour de l'image permet à chaque commande de voir les résultats des transactions nouvellement validées à partir des autres sessions. Ceci est essentiel pour un comportement cohérent quand les commandes modifient la base de données.

Quand `read_only` vaut `true`, `SPI_execute` ne met à jour ni l'image ni le compteur de commandes, et il autorise seulement les commandes `SELECT` dans la chaîne des commandes. Elles sont exécutées en utilisant l'image précédemment établie par la requête englobante. Ce mode d'exécution est un peu plus rapide que le mode lecture/écriture à cause de l'élimination de la surcharge par commande. Il autorise aussi directement la construction des fonctions stable comme les exécutions successives utiliseront toutes la même image, il n'y aura aucune modification dans les résultats.

Il n'est généralement pas conseillé de mixer les commandes en lecture seule et les commandes en lecture/écriture à l'intérieur d'une seule fonction utilisant SPI ; ceci pourrait causer un comportement portant confusion car les requêtes en mode lecture seule devraient ne pas voir les résultats de toute mise à jour de la base de données effectuées par les requêtes en lecture/écriture.

Le nombre réel de lignes pour lesquelles la (dernière) commande a été lancée est retourné dans la variable globale `SPI_processed`. Si la valeur de retour de la fonction est `SPI_OK_SELECT`, `SPI_OK_INSERT_RETURNING`, `SPI_OK_DELETE_RETURNING` ou `SPI_OK_UPDATE_RETURNING`, alors vous pouvez utiliser le pointeur global `SPITupleTable *SPI_tuptable` pour accéder aux lignes de résultat. Quelques commandes (comme `EXPLAIN`) renvoient aussi des ensembles de lignes et `SPI_tuptable` contiendra aussi le résultat dans ces cas. Certaines commandes utilitaires (`COPY`, `CREATE TABLE AS`) ne renvoient pas un ensemble de lignes, donc `SPI_tuptable` est NULL, mais elles renvoient malgré tout le nombre de lignes traitées dans `SPI_processed`.

La structure `SPITupleTable` est définie comme suit :

    +typedef struct SPITupleTable
     {
        /* Membres publics */
        TupleDesc   tupdesc;        /* descripteur de ligne */
        HeapTuple  *vals;           /* tableau de lignes */
        uint64      numvals;        /* nombre de lignes valides */

        /* Membres privés, non destinés aux appelants externes */
        uint64      alloced;        /* longueur alloué au tableau de valeurs */
        MemoryContext tuptabcxt;    /* contexte mémoire de la table résultante */
        slist_node  next;           /* lien pour la mécanique interne */
        SubTransactionId subid;     /* sous-transaction dans laquelle le tuptable a été créé */
     } SPITupleTable;

Les champs `tupdesc`, `vals`, et `numvals` peuvent être utilisés par les appelants SPI ; les champs restants sont internes. `vals` est un tableau de pointeurs vers des lignes. Le nombre de lignes est donné par `numvals` (pour des raisons un peu historiques, ce nombre est aussi renvoyé dans `SPI_processed`). `tupdesc` est un descripteur de ligne que vous pouvez passer aux fonctions SPI qui traitent des lignes.

`SPI_finish` libère tous les `SPITupleTable`s allouées pendant la fonction C courante. Vous pouvez libérer une table de résultats donnée plus tôt, si vous en avez terminé avec elle, en appelant `SPI_freetuptable`.

## Arguments

`const char * `command``

  chaîne contenant la commande à exécuter

`bool `read_only``

  `true` en cas d'exécution en lecture seule

`long `count``

  nombre maximum de lignes à traiter ou `0` pour aucune limite

## Valeur de retour

Si l'exécution de la commande a réussi, alors l'une des valeurs (positives) suivantes sera renvoyée :

`SPI_OK_SELECT`

  si un `SELECT` (mais pas `SELECT INTO`) a été lancé

`SPI_OK_SELINTO`

  si un `SELECT INTO` a été lancé

`SPI_OK_INSERT`

  si un `INSERT` a été lancé

`SPI_OK_DELETE`

  si un `DELETE` a été lancé

`SPI_OK_UPDATE`

  si un `UPDATE` a été lancé

`SPI_OK_INSERT_RETURNING`

  si un `INSERT RETURNING` a été lancé

`SPI_OK_DELETE_RETURNING`

  si un `DELETE RETURNING` a été lancé

`SPI_OK_UPDATE_RETURNING`

  si un `UPDATE RETURNING` a été lancé

`SPI_OK_UTILITY`

  si une commande utilitaire (c'est-à-dire `CREATE TABLE`) a été lancée

`SPI_OK_REWRITTEN`

  si la commande a été réécrite dans un autre style de commande (c'est-à-dire que `UPDATE` devient un `INSERT`) par une règle.

Sur une erreur, l'une des valeurs négatives suivantes est renvoyée :

`SPI_ERROR_ARGUMENT`

  si `command` est `NULL` ou `count` est inférieur à 0

`SPI_ERROR_COPY`

  si `COPY TO stdout` ou `COPY FROM stdin` ont été tentés

`SPI_ERROR_TRANSACTION`

  Si une commande de manipulation de transaction a été tentée (`BEGIN`, `COMMIT`, `ROLLBACK`, `SAVEPOINT`, `PREPARE TRANSACTION`, `COMMIT PREPARED`, `ROLLBACK PREPARED` ou toute variante de ces dernières)

`SPI_ERROR_OPUNKNOWN`

  si le type de commande est inconnu (ce qui ne devrait pas arriver)

`SPI_ERROR_UNCONNECTED`

  si appel à partir d'une fonction C non connectée

## Notes

Toutes les fonctions d'exécution de requêtes SPI changent à la fois `SPI_processed` et `SPI_tuptable` (juste le pointeur, pas le contenu de la structure). Sauvegardez ces deux variables globales dans des variables locales de fonctions C si vous voulez accéder à la table des résultats de `SPI_execute` ou d'une fonction d'exécution de requêtes sur plusieurs appels.