Aller au contenu

Migration vers 9.0 et supérieures

Contrôle des noms de variables

Dans les versions précédentes de PostgreSQL, dans une fonction PL/pgSQL, si une variable portait le même nom qu’un objet de la base, la variable était utilisée systématiquement. À partir de la version 9.0, une erreur à propos de cette ambiguïté est levée. Dans l’exemple ci-après, la table test contient une colonne nommée a :

DO LANGUAGE plpgsql
$$
DECLARE
a INT;
BEGIN
SELECT a FROM test;
END
$$
ERROR:  COLUMN reference "a" IS ambiguous
LINE 1: SELECT a FROM test
DETAIL:  It could refer TO either a PL/pgSQL variable OR a TABLE COLUMN.
QUERY:  SELECT a FROM test
CONTEXT:  PL/pgSQL FUNCTION "inline_code_block" line 4 at SQL statement

Si vous voulez modifier ce comportement, vous pouvez le faire globalement, mais il est préférable de le faire par fonction, en exécutant une de ces commandes au début de votre fonction :

#variable_conflict error        -- mode par défaut
#variable_conflict use_variable -- choisir le nom de variable
#variable_conflict use_column   -- choisir le nom de colonne

Protection des mots réservés en PL/pgSQL

L’utilisation de mot clé SQL dans le code PL/pgSQL est désormais protégée. Il faudra donc explicitement entourer le nom de ces variables de double guillemets afin de lever l’ambiguïté. de maintenant explicitement entourer le nom de ces variables de double guillemet afin de lever l’ambiguïté. Par exemple avec le code suivant :

=> DO LANGUAGE plpgsql
$$
DECLARE
TABLE INT;
BEGIN
TABLE :=TABLE+1;
END
$$;
ERROR:  syntax error at OR near "table"
LINE 6: TABLE :=TABLE+1;
             ^

La solution sera :

=> DO LANGUAGE plpgsql
$$
DECLARE
"table" INT;
BEGIN
"table" :="table"+1;
END
$$
;
DO

Echaper des bytea

En 8.4 et antérieures, les caractères non-ascii des bytea (tableaux d’octets) étaient échappés (protégés). Le format par défaut a été modifié en 9.0 :

En 8.4 :

INSERT INTO test values ('été');
SELECT * from test;
         a         
-------------------
 \303\251t\303\251

En 9.0 :

SELECT * from test;
      a       
--------------
 \xc3a974c3a9

En 8.4, seules les valeurs d’octet ne correspondant pas à des caractères ASCII sont protégées. En 9.0, tout est codé directement en hexadécimal.

La chaîne été saisie est en Unicode (UTF-8). Elle est donc composée de la séquence d’octets suivante (en hexadécimal): c3 a9 74 c3 a9.

c3 a9 est le caractère é (encodé sur 2 octets en UTF8). t, quant à lui, fait partie des caractères ASCII, et est donc encodé sur un seul caractère, le même qu’en ASCII (74).

Le nouveau format 9.0 est donc \xXXXXXXXXXXXX, chaque paire de XX correspondant à la valeur d’un octet, en valeur hexadécimale.

L’ancien format ne protège que les valeurs d’octet non transposable en ASCII (ici, le é), sous la forme \DDD (valeur décimale de l’octet). Ce format est souvent moins compact, et beaucoup plus lent à coder et décoder, puisque nécessitant des tests sur la présence d’un \ ou non, ou des comportements différents suivant la valeur ASCII d’un caractère.

Le nouveau format est donc à privilégier, si vous pouvez modifier votre application (si vous traitez vous-mêmes les bytea dans le code), ou si vous pouvez modifier votre driver (le driver JDBC 9.0, par exemple, autodétecte le type d’encodage et fait de lui-même ce qui est nécessaire).

Si vous ne pouvez pas modifier l’application, il est possible de revenir à l’ancien fonctionnement, en modifiant le paramètre bytea_output à escape au lieu de sa valeur par défaut hex. Mais vous ne bénéficierez pas du gain de performance apporté par le nouveau format. `