Migration vers 9.1 et supérieures¶
standard_conforming_strings
¶
La valeur par défaut du paramètre standard_conforming_strings
est passée à on
. Traditionnellement,
PostgreSQL ne traitait pas les littéraux de types chaîne (..
) comme le spécifie le standard SQL,
car les anti-slashs (\
) étaient considérés comme des caractères d’échappement, ce qui entraînait
que le caractère suivant un \
était interprété. Par exemple, \n
est un caractère newline, \\
est
le caractère \
lui-même, etc… En 9.1
, le paramètre standard_conforming_strings
est maintenant par
défaut à on
, ce qui signifie que les littéraux de type chaîne sont maintenant traités comme
spécifiés par le standard SQL. Le caractère apostrophe doit maintenant être protégé avec une
deuxième apostrophe plutôt qu’un anti-slash, et les anti-slashs ne sont plus des caractères
d’échappement. Par exemple, quand précédemment on écrivait 'l\'heure'
, on doit maintenant écrire
'l''heure'
.
Certaines subtilités sont à connaître, même si elles ne sont pas apparues en 9.1:
- l’ancienne syntaxe est toujours disponible : mettez simplement un
E
devant le guillemet de départ:E'l\'heure'
standard_conforming_strings
peut toujours être remis à off- Beaucoup de langages de programmation font déjà ce qu’il faut si vous leur demandez de faire le
travail d’échappement pour vous. Par exemple, la fonction
PQescapeLiteral
de lalibpq
détecte automatiquement la valeur destandard_conforming_strings
et s’y adapte, pour peu qu’elle soit suffisamment récente.
Conversions de type composite¶
Les conversions de type de données de style fonction
ou `attribut’ ne sont plus autorisées pour
les types composites.
Depuis la version 8.4, il est possible de convertir à peu près n’importe quoi vers son format
texte. Essayons cela avec une table statistical_data
contenant deux colonnes numeric
:
texte. Essayons cela avec une table statistical_data
contenant deux colonnes numeric
:
SELECT cast(statistical_data as text) from statistical_data ;
statistical_data
------------------
(0.1,0.2)
(0.2,0.4)
(0.3,0.9)
(0.4,1.6)
(4 rows)
Le problème est que les versions 8.4 et 9.0 nous donnent quatre syntaxes différentes pour effectuer cela :
SELECT cast(statistical_data as text) from statistical_data ;
SELECT statistical_data::text from statistical_data;
SELECT statistical_data.text from statistical_data;
SELECT text(statistical_data) from statistical_data;
Les deux dernières syntaxes ne sont plus autorisées pour les types composites (comme un enregistrement de table) : ils étaient bien trop faciles à utiliser accidentellement.
Vérification de contraintes sur des domaines de type tableau¶
Les vérifications de conversion sur les domaines définis à partir de tableaux ont été renforcées. Maintenant, PostgreSQL vérifie quand vous faites une mise à jour d’un élément d’une contrainte définie sur un tableau. Voici ce qui se passait en 9.0 :
CREATE DOMAIN test_dom as int[] check (value[1] > 0);
SELECT '{-1,0,0,0,0}'::test_dom;
ERROR: value for domain test_dom violates check constraint "test_dom_check"
Jusque là, tout va bien.
CREATE TABLE test_dom_table (test test_dom);
INSERT INTO test_dom_table values ('{1,0,0,0,0}');
INSERT 0 1
UPDATE test_dom_table SET test[1]=-1;
Par contre, là, c’est anormal… la contrainte check nous interdit de le faire. C’est maintenant impossible en 9.1, la vérification est faite correctement.
Modification de string_to_array()
¶
string_to_array()
retourne maintenant un tableau vide pour une chaîne d’entrée de longueur zéro.
Précédemment, cela retournait NULL
.
string_to_array()
découpe maintenant une chaîne en ses caractères si le séparateur est NULL
.
Précédemment, cela retournait NULL
:
Modification de RAISE
dans PL/pgSQL¶
RAISE
dans PL/pgSQL sans paramètre a changé de comportement.
C’est un cas assez rare, mais qui piégeait les utilisateurs habitués au comportement d’Oracle sur ce point.
Voici un exemple :
CREATE OR REPLACE FUNCTION raise_demo () RETURNS void LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'Main body';
BEGIN
RAISE NOTICE 'Sub-block';
RAISE EXCEPTION serialization_failure; -- Simulate a problem
EXCEPTION WHEN serialization_failure THEN
BEGIN
-- Maybe we had a serialization error
-- Won't happen here of course
RAISE DEBUG 'There was probably a serialization failure. It could be because of...';
-- ..
-- If I get there let's pretend I couldn't find a solution to the error
RAISE; -- Let's forward the error
EXCEPTION WHEN OTHERS THEN
-- This should capture everything
RAISE EXCEPTION 'Couldn t figure what to do with the error';
END;
END;
END;
$$
;
En 9.0, vous aurez ce résultat (avec client_min_messages
à debug
) :
SELECT raise_demo();
NOTICE: Main body
NOTICE: Sub-block
DEBUG: There was probably a serialization failure. It could be because of...
ERROR: serialization_failure
En 9.1 :
SELECT raise_demo();
NOTICE: Main body
NOTICE: Sub-block
DEBUG: There was probably a serialization failure. It could be because of...
ERROR: Couldn t figure what to do with the error
La différence est que RAISE
sans paramètres, en 9.0, ramène le déroulement du code à
l’endroit où l’EXCEPTION
s’est déclenchée. En 9.1, le RAISE
continue dans le bloc dans
lequel il se produit, le bloc BEGIN
intérieur n’est pas quitté quand le RAISE
se déclenche.
Son bloc d’exception est exécuté.