Il y a deux façons de gérer cela. La première consiste à préparer la chaîne avec les valeurs qui y sont insérées. La seconde consiste à utiliser des paramètres de requête pour lesquels vous pouvez substituer des valeurs séparément.
Pour la première méthode, vous pouvez utiliser une fonction telle que snprintf pour préparer la commande que vous enverrez au serveur. Par exemple :
char buffer[512];
int num=snprintf(buffer, sizeof(buffer),
"SELECT name FROM MYTABLE WHERE id=%d", id);
if (num>sizeof(buffer)) {
/* error: buffer was too small */
}
Après ce buffer contiendra la requête SQL incluant la valeur réelle de la variable id.
Notez la nécessité de vérifier la valeur de retour de snprintf pour voir si le tampon a débordé.
Notez également que lorsqu'une chaîne est placée dans la commande, vous devez vous assurer que la chaîne ne contient pas de guillemets ou d'autres caractères spéciaux. Si la chaîne provient de l'extérieur de votre programme, par exemple. À partir de l'entrée de l'utilisateur, le fait de ne pas le citer correctement laisse un grand trou à travers lequel quelqu'un pourrait injecter du SQL malveillant. libpq fournit le PQescapeLiteral fonction pour cela.
L'autre méthode, préférable dans la plupart des cas, consiste à transmettre la commande SQL et les paramètres au serveur séparément. Par exemple, vous pouvez le faire en utilisant PQexecParams fonction libpq. Votre chaîne SQL ressemblerait à ceci :
PGresult r = PQexecParams(conn, /* Connection to database */
"SELECT name FROM mytable WHERE id=$1",
1, /* Number of parameters */
NULL, /* NULL means server should figure out the parameter types */
params, /* Pointer to array of strings containing parameters */
NULL, /* Not needed unless binary format used */
NULL, /* Not needed unless binary format used */
0 /* Result to come back in text format */
);
Cette fonction permet de fournir des paramètres et/ou d'obtenir des résultats au format texte ou binaire. Pour plus de simplicité, mon exemple ci-dessus suppose un format texte pour les deux.
Une variante consiste à utiliser des instructions préparées. Dans ce cas, vous effectuez deux appels distincts à libpq :
-
Appelez PQprepare, auquel vous transmettez votre instruction SQL avec les valeurs de paramètre $1, $2, etc., comme dans mon exemple ci-dessus. Cela renverra un handle d'instruction.
-
Appelez PQexecPrepared, auquel vous transmettez le descripteur d'instruction ainsi que les paramètres eux-mêmes, spécifiés de la même manière que PQexecParams.
L'avantage d'utiliser deux étapes comme celle-ci est que vous pouvez préparer l'instruction une seule fois et l'exécuter plusieurs fois, ce qui réduit la surcharge du serveur associée à son analyse et à la planification de la requête.