38.5. Accès à la base de données depuis PL/Tcl

Les commandes suivantes sont disponibles pour accéder à la base de données depuis le corps d'une fonction PL/Tcl :

spi_exec ?-count n? ?-array name? command ?loop-body?

Exécute une commande SQL donnée en tant que chaîne. Une erreur dans la commande lève une erreur. Sinon, la valeur de retour de spi_exec est le nombre de lignes intéressées dans le processus (sélection, insertion, mise à jour ou suppression) par la commande ou zéro si la commande est une instruction utilitaire. De plus, si la commande est une instruction SELECT, les valeurs des données sélectionnées sont placées dans des variables Tcl décrites ci-dessous.

La valeur optionnelle -count indique à spi_exec le nombre maximum de lignes à travailler dans la commande. L'effet de ceci est comparable à l'initialisation d'une requête en tant que curseur et de dire FETCH n.

Si la commande est une instruction SELECT, les valeurs des colonnes de résultat sont placées dans les variables Tcl nommées d'après les colonnes. Si l'option -array est donnée, les valeurs de colonnes sont stockées à la place dans un tableau associatif nommé, avec les noms des colonnes utilisés comme index du tableau.

Si la commande est une instruction SELECT et qu'aucun script loop-body n'est donné, alors seule la première ligne de résultats est stockée dans des variables Tcl ; les lignes suivantes sont ignorées. Aucun stockage n'intervient si la requête ne renvoie pas de ligne (ce cas est détectable avec le résultat de la fonction spi_exec). Par exemple,

spi_exec "SELECT count(*) AS cnt FROM pg_proc"

initialisera la variable Tcl $cnt avec le nombre de lignes dans le catalogue système pg_proc.

Si l'argument loop-body optionnel est donné, il existe un morceau de script Tcl qui est exécuté une fois pour chaque ligne du résultat de la requête (loop-body est ignoré si la commande donnée n'est pas un SELECT). Les valeurs des colonnes de la ligne actuelle sont stockées dans des variables Tcl avant chaque itération. Par exemple,

spi_exec -array C "SELECT * FROM pg_class" {
    elog DEBUG "have table $C(relname)"
}

affichera un message de trace pour chaque ligne de pg_class. Cette fonctionnalité travaille de façon similaire aux autres constructions de boucles de Tcl ; en particulier, continue et break fonctionnent de la même façon à l'intérieur de loop-body.

Si une colonne d'un résultat de la requête est nulle, la variable cible est << dés-initialisée >> plutôt qu'initialisée.

spi_prepare query typelist

Prépare et sauvegarde un plan de requête pour une exécution future. Le plan sauvegardé sera conservé pour la durée de la session actuelle.

La requête peut utiliser des paramètres, c'est-à-dire des emplacements pour des valeurs à fournir lorsque le plan sera réellement exécuté. Dans la chaîne de requête, faites référence aux paramètres avec les symboles $1 ... $n. Si la requête utilise les paramètres, les noms des types de paramètre doivent être donnés dans une liste Tcl (écrivez une liste vide pour typelist si aucun paramètre n'est utilisé). Actuellement, les types de paramètres doivent être identifiés par les noms de types internes affichés dans la table système pg_type ; par exemple int4 et non pas integer.

La valeur de retour de spi_prepare est l'identifiant de la requête à utiliser dans les appels suivants à spi_execp. Voir spi_execp pour un exemple.

spi_execp ?-count n? ?-array name? ?-nulls string? queryid ?value-list? ?loop-body?

Exécute une requête préparée précédemment avec spi_prepare. queryid est l'identifiant renvoyé par spi_prepare. Si la requête fait référence à des paramètres, une liste de valeurs (value-list) doit être fournie. C'est une liste Tcl des valeurs réelles des paramètres. La liste doit être de la même longueur que la liste de types de paramètres donnée précédemment lors de l'appel à spi_prepare. Oubliez-la si la requête n'a pas de paramètres.

La valeur optionnelle pour -nulls est une chaîne d'espaces et de caractères 'n' indiquant à spi_execp les paramètres nuls. Si indiqué, elle doit avoir exactement la même longueur que value-list. Si elle est omise, toutes les valeurs de paramètres sont non nulles.

Sauf si la requête et ses paramètres sont spécifiés, spi_execp fonctionne de la même façon que spi_exec. Les options -count, -array et loop-body sont identiques. Du coup, la valeur du résultat l'est aussi.

Voici un exemple d'une fonction PL/Tcl utilisant un plan préparé :

CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS '
    if {![ info exists GD(plan) ]} {
        # prépare le plan sauvegardé au premier appel
        set GD(plan) [ spi_prepare \\
                "SELECT count(*) AS cnt FROM t1 WHERE num >= \\$1 AND num <= \\$2" \\
                [ list int4 int4 ] ]
    }
    spi_execp -count 1 $GD(plan) [ list $1 $2 ]
    return $cnt
' LANGUAGE pltcl;

Notez que chaque anti-slash que Tcl doit voir doit être doublé lorsque vous saisissez la fonction car l'analyseur principal gère les anti-slashs dans CREATE FUNCTION. Nous avons besoin des anti-slashs dans la requête fournie à spi_prepare pour nous aussrer que les marqueurs $n seront passés de façon identique à spi_prepare et non pas une substitution de variable par Tcl.

spi_lastoid

Renvoie l'OID de la ligne insérée par le dernier appel à spi_exec ou spi_execp, si la commande était un INSERT d'une seule ligne. (Sinon, vous obtenez zéro.)

quote string

Duplique toutes les occurrences de guillemet simple et d'anti-slash dans la chaîne donnée. Ceci peut être utilisé pour mettre entre guillemets des chaînes de façon sûr et pour qu'elles puissent être insérées dans des commandes SQL passées à spi_exec ou spi_prepare. Par exemple, pensez à une chaîne de commande SQL comme :

"SELECT '$val' AS ret"

où la variable Tcl val contient actuellement le mot doesn't. Ceci finirait avec la chaîne de commande :

SELECT 'doesn't' AS ret

qui va causer une erreur d'analyse lors de spi_exec ou de spi_prepare. La commande soumise devrait contenir

SELECT 'doesn''t' AS ret

qui peut-être créé avec PL/Tcl en utilisant

"SELECT '[ quote $val ]' AS ret"

Un avantage de spi_execp est que vous n'avez pas à mettre entre guillemets des valeurs de paramètres comme ceux-ci car les paramètres ne sont jamais analysés comme faisant partie de la chaîne de la commande SQL.

elog level msg

Émet une trace ou un message d'erreur. Les niveaux possibles sont DEBUG, LOG, INFO, NOTICE, WARNING, ERROR et FATAL. La plupart ne font qu'émettre le message donné de la même façon que la fonction C elog. ERROR élève une condition d'erreur : une exécution prochaine de la fonction est abandonnée et la transaction actuelle est annulée. FATAL annule la transaction et fait que la session courante s'arrête. (Il n'existe probablement aucune raison d'utiliser ce niveau d'erreur dans les fonctions PL/Tcl mais il est fourni pour que tous les messages soient tout de même disponibles.)