Vous n'êtes pas identifié(e).
Problème d’exécution d’un programme ecpg (postgresql 8.4.10 serveur red hat enterprise 5.3 64 bit ).
Bonjour,
J’ai un problème dû à la migration d’une base de données 8.2.4 vers 8.4.10.
Le problème se situe au niveau d’un programme C incluant du sql en un mot ECPG
La compilation du programme est OK.
Lors de l’exécution de mon programme j ai un bug :
SQL error: syntax error at or near "$1" on line 367
SQL error: too many arguments on line 368
SQL error: invalid statement name "stmt_select_timestamp" on line 369
ci-dessous les lignes de code incriminées :
EXEC SQL BEGIN DECLARE SECTION;
/* calcul la date de creation du message dans la table */
const char *select_timestamp = "SELECT ( now()- interval ? )::varchar";
EXEC SQL END DECLARE SECTION;
memset(timestamp_d, '\0', TAILLE_BUFFER);
memset(date, '\0', TAILLE_BUFFER);
sprintf(date," %s days",360);
EXEC SQL WHENEVER SQLERROR SQLPRINT
EXEC SQL PREPARE stmt_select_timestamp FROM :select_timestamp;
EXEC SQL EXECUTE stmt_select_timestamp INTO :timestamp_d USING :date;
EXEC SQL DEALLOCATE PREPARE stmt_select_timestamp;
timestamp_d[11] = NUL;
Hors ligne
Il me semble qu'il manque les guillemets autour du point d'interrogation. Cela étant dit, même si j'ai fait un peu d'ECPG, je suis loin d'être un expert.
Guillaume.
Hors ligne
En version 8.2 ECPG injecte certainement le paramètre dans la requête, sans utiliser le PREPARE côté serveur.
Mais depuis 8.3, ECPG utilise le PREPARE côté serveur (voir les notes de version de la doc).
Or le vrai PREPARE est strict sur ce qui peut être paramètre ou pas, en gros seuls les litéraux peuvent être des paramètres. DAYS étant un mot clef et non un litéral, l'expression "360 DAYS" ne convient pas comme paramètre.
C'est un problème, les autres interfaces comme PDO ou DBD::Pg qui ont opté pour les PREPARE côté serveur ont le même.
La solution est de faire en SQL:
PREPARE stmt_X as SELECT ( now()- $1 * '1 day'::interval )::varchar
et de passer juste le nombre de jours dans le paramètre, sans "DAYS" évidemment.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Merci pour les informations et les précisions.
Pour la communauté, le code corrigé et testé a partir des informations données par Monsieur "dverite".
EXEC SQL BEGIN DECLARE SECTION;
/* calcul la date de creation du message dans la table */
const char *select_timestamp = "SELECT ( now()- ? * '1 day'::interval )::varchar";
EXEC SQL END DECLARE SECTION;
memset(timestamp_d, '\0', TAILLE_BUFFER);
memset(date, '\0', TAILLE_BUFFER);
sprintf(date,"%s",360);
EXEC SQL WHENEVER SQLERROR SQLPRINT
EXEC SQL PREPARE stmt_select_timestamp FROM :select_timestamp;
EXEC SQL EXECUTE stmt_select_timestamp INTO :timestamp_d USING :date;
EXEC SQL DEALLOCATE PREPARE stmt_select_timestamp;
timestamp_d[11] = NUL;
Hors ligne