PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17 RC1 » Interfaces client » libpq -- Bibliothèque C » Annuler des requêtes en cours d'exécution

32.7. Annuler des requêtes en cours d'exécution #

32.7.1. Fonctions pour envoyer des demandes d'annulation #

PQcancelCreate #

Prépare une connexion sur laquelle une demande d'annulation peut être envoyée.

PGcancelConn *PQcancelCreate(PGconn *conn);

PQcancelCreate crée un objet PGcancelConn mais elle ne va pas commencer immédiatement l'envoi d'une demande d'annulation sur cette connexion. Une demande d'annulation peut être envoyée sur cette connexion d'une façon bloquante en utilisant PQcancelBlocking et d'une façon non bloquante en utilisant PQcancelStart. La valeur de retour peut être passée à PQcancelStatus pour vérifier si l'objet PGcancelConn a été créé avec succès. L'objet PGcancelConn est une structure opaque qui ne doit pas être accédée directement par l'application. Cet objet PGcancelConn peut être utilisé pour annuler la requête en cours d'exécution sur la connexion originale d'une façon sûre avec des threads.

Beaucoup de paramètres de connexion du client original seront réutilisés lors de la configuration de la connexion pour la demande d'annulation. Si la connexion originiale nécessite le chiffrement de la connexion et/ou la vérification de l'hôte cible (en utilisant sslmode ou gssencmode), alors la connexion pour la demande d'annulation est faite avec les mêmes prérequis. Toute option de connexion utilisée pendant et après l'authentification du client est cependant ignorée car les demandes d'annulation ne nécessitent pas d'authentification et la connexion est fermée immédiatement après la soumission de la demande d'annulation.

Notez que quand PQcancelCreate renvoie un pointeur non nul, vous devez appeler PQcancelFinish quand vous en avez fini avec lui pour libérer la structure et tout bloc mémoire associé. Ceci doit être fait même si la demande d'annulation a échoué ou a été abandonnée.

PQcancelBlocking #

Demande que le serveur abandonne le traitement de la commande en cours d'une façon bloquante.

int PQcancelBlocking(PGcancelConn *cancelConn);

Cette demande est faite au travers d'un objet PGcancelConn, qui doit être créé avec PQcancelCreate. La valeur de retour de PQcancelBlocking vaut 1 si la demande d'annulation a été envoyée avec succès et 0 dans le cas contraire. Sans succès, le message d'erreur peut être récupéré en utilisant PQcancelErrorMessage .

L'envoi avec succès de l'annulation n'est cependant pas une garantie que la demande réussisse. Si l'annulation est bien faite, la commande en cours d'annulation terminera rapidement et renverra un résultat en erreur. Si l'annulation échoue (par exemple parce que le serveur avait déjà terminé l'exécution de la commande), alors aucun résultat ne sera visible.

PQcancelStart
PQcancelPoll #

Demande que le serveur abandonne le traitement de la commande en cours d'une façon non bloquante.

int PQcancelStart(PGcancelConn *cancelConn);

PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);

Cette demande est faite au travers d'un objet PGcancelConn, qui doit être créé avec PQcancelCreate. La valeur de retour de PQcancelBlocking vaut 1 si la demande d'annulation a été envoyée avec succès et 0 dans le cas contraire. Sans succès, le message d'erreur peut être récupéré en utilisant PQcancelErrorMessage .

Si PQcancelStart réussit, la prochaine étape revient à interroger libpq pour qu'il puisse traiter la séquence de connexion d'annulation. Utilisez PQcancelSocket pour obtenir le descripteur de la socket de la connexion à la base (attention, ne supposez pas que la socket sera identique après plusieurs appels à PQcancelPoll). En boucle : si PQcancelPoll(cancelConn) renvoie PGRES_POLLING_READING, attendez jusqu'à ce que la socket soit prête en lecture (comme indiqué par select(), poll(), ou tout fonction système similaire). Puis appelez PQcancelPoll(cancelConn) de nouveau. Inversement, si PQcancelPoll(cancelConn) renvoie PGRES_POLLING_WRITING, attendez jusqu'à ce que la socket soit disponible en écriture, puis appelez de nouveau PQcancelPoll(cancelConn). Sur la première itération, si vous avez encore besoin d'appeler PQcancelPoll(cancelConn), faites comme si elle avait renvoyé PGRES_POLLING_WRITING. Continuez cette boucle jusqu'à ce que PQcancelPoll(cancelConn) renvoie PGRES_POLLING_FAILED, indiquant que la procédure de connexion a échoué ou PGRES_POLLING_OK, indiquant que la demande d'annulation a été envoyée avec succès.

L'envoi avec succès de l'annulation n'est cependant pas une garantie que la demande réussisse. Si l'annulation est bien faite, la commande en cours d'annulation terminera rapidement et renverra un résultat en erreur. Si l'annulation échoue (par exemple parce que le serveur avait déjà terminé l'exécution de la commande), alors aucun résultat ne sera visible.

À tout moment pendant la connexion, le statut de cette connexion peut être vérifié en appelant PQcancelStatus. Si cet appel renvoie CONNECTION_BAD, alors la procédure d'annulation a échoué ; si l'appel renvoie CONNECTION_OK, alors la demande d'annulation a été correctement envoyée. Ces deux statuts sont détectables à partir de la valeur renvoyée par PQcancelPoll, décrite ci-dessus. D'autres statuts peuvent aussi survenir, mais seulement lors d'une procédure de connexion asynchrone. Elles indiquent l'étape actuelle de la procédure de connexion et pourraient être utiles, par exemple pour donner des informations à l'utilisateur. Ces statuts sont :

CONNECTION_ALLOCATED #

En attente d'un appel à PQcancelStart ou PQcancelBlocking, pour réellement ouvrir la socket. Cela correspond au statut de la connexion tout de suite après un appel à PQcancelCreate ou PQcancelReset. Aucun connexion au serveur n'a encore été initiée à ce point. Pour réellement commencer l'envoi de la demande d'annulation, utilisez PQcancelStart ou PQcancelBlocking.

CONNECTION_STARTED #

En attente de la connexion.

CONNECTION_MADE #

Connexion OK ; en attente de l'envoi.

CONNECTION_AWAITING_RESPONSE #

En attente d'une réponse du serveur.

CONNECTION_SSL_STARTUP #

Négociation d'un chiffrement SSL.

CONNECTION_GSS_STARTUP #

Négociation d'un chiffrement GSS.

Notez que, bien que ces constantes resteront (pour maintenir la compatibilité), une application ne devrait jamais se baser sur leur arrivée dans un ordre précis ou du tout. Elle ne devrait pas plus se baser sur l'inexistence d'autres statuts. Une application pourrait faire quelque chose comme :

switch(PQcancelStatus(conn))
{
        case CONNECTION_STARTED:
            feedback = "Connecting...";
            break;

        case CONNECTION_MADE:
            feedback = "Connected to server...";
            break;
.
.
.
        default:
            feedback = "Connecting...";
}

Le paramètre de connexion connect_timeout est ignoré lors de l'utilisation de PQcancelPoll ; c'est de la responsabilité de l'application de décider si trop de temps s'est écoulé. Sinon, PQcancelStart suivi d'une boucle PQcancelPoll est équivalent à PQcancelBlocking.

PQcancelStatus #

Renvoie le statut de la demande d'annulation.

ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);

Le statut peut avoir différentes valeurs. Néanmoins, seules trois de ces valeurs sont vues en dehors d'une procédure d'annulation asynchrone : CONNECTION_ALLOCATED, CONNECTION_OK et CONNECTION_BAD. Le statut initial d'un objet PGcancelConn créé avec succès en utilisant PQcancelCreate est CONNECTION_ALLOCATED. Une demande d'annulation qui a été correctement envoyée a le statut CONNECTION_OK. Une tentative échouée d'annulation est signalée par le statut CONNECTION_BAD. Un statut OK restera jusqu'à ce que PQcancelFinish ou PQcancelReset soit appelé.

Voir l'entrée pour PQcancelStart concernant les autres statuts pouvant être renvoyés.

L'envoi avec succès de l'annulation n'est cependant pas une garantie que la demande réussisse. Si l'annulation est bien faite, la commande en cours d'annulation terminera rapidement et renverra un résultat en erreur. Si l'annulation échoue (par exemple parce que le serveur avait déjà terminé l'exécution de la commande), alors aucun résultat ne sera visible.

PQcancelSocket #

Obtient le numéro du descripteur de fichier du socket de la connexion d'annulation au serveur.

int PQcancelSocket(const PGcancelConn *cancelConn);

Un descripteur valide sera supérieur ou égale à 0 ; un résultat -1 indiquera qu'aucune connexion n'est actuellement ouverte vers le serveur. Ceci pourrait changer suite à l'appel d'une des fonctions de cette section sur l'objet PGcancelConn (sauf pour PQcancelErrorMessage et PQcancelSocket).

PQcancelErrorMessage #

Renvoie le message d'erreur généré le plus récemment par une opération sur la connexion d'annulation.

char *PQcancelErrorMessage(const PGcancelConn *cancelconn);

Pratiquement toutes les fonctions libpq qui prennent un objet PGcancelConn enverra un message pour PQcancelErrorMessage si elles échouent. Notez que par une convention de la libpq, un résultat PQcancelErrorMessage non vide peut contenir plusieurs lignes et incluera une nouvelle ligne à la fin. L'appelant ne doit pas libérer directement le résultat. Il sera libéré quand l'objet PGcancelConn associé est passé à PQcancelFinish. La chaîne résultante ne doit pas s'attendre à rester identique tout au long des opérations sur la structure PGcancelConn.

PQcancelFinish #

Ferme la connexion d'annulation (si elle n'a pas encore envoyée la demande d'annulation). De plus, libère la mémoire utilisée par l'objet PGcancelConn.

void PQcancelFinish(PGcancelConn *cancelConn);

Notez que même si la tentative d'annulation échoué (comme indiquée par PQcancelStatus), l'application doit appeler PQcancelFinish pour libérer la mémoire utilisée par l'objet PGcancelConn. Le pointeur PGcancelConn ne doit pas être utilisé de nouveau après l'appel de PQcancelFinish.

PQcancelReset #

Réinitialise l'objet PGcancelConn pour qu'il puisse être réutilisé pour une nouvelle connexion d'annulation.

void PQcancelReset(PGcancelConn *cancelConn);

Si l'objet PGcancelConn est actuellement utilisé pour envoyer une demande d'annulation, alors cette connexion est fermée. Il préparera alors l'objet PGcancelConn de façon à ce qu'il puisse être utilisé pour une nouvelle demande d'annulation.

Cette fonction peut être utilisé pour créer un objet PGcancelConn pour un objet PGconn et pour le réutiliser plusieurs fois tout au long de la vie de l'objet PGconn original.

32.7.2. Fonctions obsolètes pour l'envoi de demandes d'annulation #

Ces fonctions représentent d'anciennes méthodes pour l'envoi de demandes d'annulation. Bien qu'elles fonctionnent toujours, elles ne sont pas recommendées car elles n'envoient pas les demandes d'annulation d'une façon chiffrée, même quand la connexion originale réclamait le chiffrement avec sslmode ou gssencmode. De ce fait, l'utilisation des anciennes méthodes dans du nouveau code est fortement déconseillée, et il est fortement recommandé de modifier le code existant pour utiliser à la place les nouvelles fonctions.

PQgetCancel #

Crée une structure de données contenant les informations nécessaires à l'annulation d'une commande en utilisant PQcancel .

PGcancel *PQgetCancel(PGconn *conn);
       

PQgetCancel crée un objet PGcancel à partir d'un objet connexion PGconn. Il renverra NULL si le paramètre conn donné est NULL ou est une connexion invalide. L'objet PGcancel est une structure opaque qui n'a pas pour but d'être accédé directement par l'application ; elle peut seulement être passée à PQcancel ou PQfreeCancel .

PQfreeCancel #

Libère une structure de données créée par PQgetCancel .

void PQfreeCancel(PGcancel *cancel);
       

PQfreeCancel libère un objet donné par PQgetCancel .

PQcancel #

Demande que le serveur abandonne l'exécution de la commande en cours. PQcancel est une variante obsolète et non sécurisée PQcancelBlocking, mais elle peut être utilisée à l'intérieur d'un gestionnaire de signaux.

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
       

PQcancel existe uniquement pour des raisons de rétro-compatibilité. PQcancelBlocking doit être utilisé à la place. Le seul avantage de PQcancel est qu'il peut être utilisé en toute sécurité à partir d'un gestionnaire de signaux, si errbuf est une variable locale dans le gestionnaire de signaux. Néanmoins, ce bénéfice n'est pas suffisamment important par rapport aux risques de faille de sécurité que comporte cette fonction.

L'objet PGcancel est en lecture seule pour ce qui concerne PQcancel , donc il peut aussi être appelé à partir d'un thread qui est séparé de celui qui manipule l'objet PGconn.

La valeur de retour de PQcancel est 1 si la demande d'annulation a été envoyée avec succès, et 0 sinon. Dans ce dernier cas, errbuf contient un message d'erreur d'explication. errbuf doit être un tableau de caractères dont la taille correspond à errbufsize (la taille recommandée est de 256 octets).

PQrequestCancel #

PQrequestCancel est une variante obsolète et non sécurisée de PQcancelBlocking.

int PQrequestCancel(PGconn *conn);
       

PQrequestCancel existe uniquement pour des raisons de compatibilité ascendante. PQcancelBlocking peut être utilisé à la place. Il n'y a pas d'intérêt à utiliser PQrequestCancel à la place de PQcancelBlocking.

Demande au serveur l'abandon du traitement de la commande en cours d'exécution. Elle opère directement sur l'objet PGconn et, en cas d'échec, stocke le message d'erreur dans l'objet PGconn (d'où il peut être récupéré avec PQerrorMessage ). Bien qu'il s'agisse de la même fonctionnalité, cette approche n'est pas sûre dans les programmes multi-threads et les gestionnaires de signaux car il est possible que la surcharge du message d'erreur de PGconn gênera l'opération en cours sur la connexion.