Le mélange de différents types de données dans la même expression
peut être requis, intentionnellement ou pas, par les instructions
SQL. PostgreSQL™ possède des fonctionnalités
étendues pour évaluer les expressions de type mixte.
Dans la plupart des cas, un utilisateur n'aura pas besoin de
comprendre les détails du mécanisme de conversion des types.
Cependant, les conversions implicites faites par PostgreSQL™ peuvent affecter le résultat
d'une requête. Quand cela est nécessaire, ces résultats peuvent être
atteints directement en utilisant la conversion
explicite
de types.
Ce chapitre introduit les mécanismes et les conventions sur les
conversions de types dans PostgreSQL™. Référez-vous aux sections
appropriées du Chapitre 8, Types de
données et du Chapitre 9,
Fonctions et opérateurs pour plus d'informations sur les types de
données spécifiques, les fonctions et les opérateurs autorisés.
10.1. Aperçu
SQL est un langage fortement
typé. C'est-à-dire que chaque élément de données est associé à un
type de données qui détermine son comportement et son utilisation
permise. PostgreSQL™ a un
système de types extensible qui est beaucoup plus général et
flexible que les autres implémentations de SQL. Par conséquent, la plupart des
comportements de conversion de types dans PostgreSQL™ est régie par des règles
générales plutôt que par une heuristique
ad hoc
. Cela
permet aux expressions de types mixtes d'être significatives même
avec des types définis par l'utilisateur.
L'analyseur de PostgreSQL™
divise les éléments lexicaux en seulement cinq catégories
fondamentales : les entiers, les nombres non entiers, les chaînes
de caractères, les identifieurs et les mots-clé. Les constantes de
la plupart des types non-numériques sont d'abord classifiées comme
chaînes de caractères. La définition du langage SQL permet de spécifier le nom des types avec
une chaîne et ce mécanisme peut être utilisé dans PostgreSQL™ pour lancer l'analyseur sur
le bon chemin. Par exemple, la requête
SELECT text 'Origin' AS "label", point '(0,0)' AS "value";
label | value
--------+-------
Origin | (0,0)
(1 row)
a deux constantes littérales, de type text et point. Si un type
n'est pas spécifié pour une chaîne littérale, alors le type
unknown est assigné initialement pour
être résolu dans les étapes ultérieures comme décrit plus bas.
Il y a quatre constructions SQL
fondamentales qui exigent des règles distinctes de conversion de
types dans l'analyseur de PostgreSQL™ :
-
Les appels de fonctions
-
Une grande partie du système de types de PostgreSQL™ est construit autour
d'un riche ensemble de fonctions. Les fonctions peuvent avoir
un ou plusieurs arguments. Puisque que PostgreSQL™ permet la surcharge
des fonctions, le nom seul de la fonction n'identifie pas de
manière unique la fonction à appeler ; l'analyseur doit
sélectionner la bonne fonction par rapport aux types des
arguments fournis.
-
Les opérateurs
-
PostgreSQL™ autorise
les expressions avec des opérateurs de préfixe et de suffixe
unaires (un argument) aussi bien que binaires (deux
arguments). Comme les fonctions, les opérateurs peuvent être
surchargés. Du coup, le même problème existe pour
sélectionner le bon opérateur.
-
Le stockage des valeurs
-
Les instructions SQL
INSERT
et
UPDATE
placent
le résultat des expressions dans une table. Les expressions
dans une instruction doivent être en accord avec le type des
colonnes cibles et peuvent être converties vers celles-ci.
-
Les constructions UNION, CASE et des
constructions relatives
-
Comme toutes les requêtes issues d'une instruction
SELECT
utilisant une union doivent apparaître dans un ensemble
unique de colonnes, les types de résultats de chaque
instruction
SELECT
doivent être
assortis et convertis en un ensemble uniforme. De façon
similaire, les expressions de résultats d'une construction
CASE doivent être converties vers un
type commun de façon à ce que l'ensemble de l'expression
CASE ait un type de sortie connu.
Cela est la même chose pour les constructions avec ARRAY et pour les fonctions GREATEST et LEAST.
Les catalogues systèmes stockent les informations concernant la
validité des conversions entre les types de données et la façon
d'exécuter ces conversions. Les conversions sont appelées
casts en anglais. Des conversions de
types supplémentaires peuvent être ajoutées par l'utilisateur avec
la commande
CREATE
CAST
(c'est habituellement réalisé en conjonction
avec la définition de nouveaux types de données. L'ensemble des
conversions entre les types prédéfinis a été soigneusement choisi
et le mieux est de ne pas le modifier).
Concernant les types SQL
standards, une heuristique additionnelle est fournie dans
l'analyseur pour permettre de meilleures estimations du
comportement approprié. Il y a plusieurs catégories de types basiques définies :
boolean, numeric, string,
bitstring, datetime, timespan,
geometric, network et utilisateurs. Chaque catégorie, à
l'exception des types définis par l'utilisateur, a un ou plusieurs
types pré-définis qui sont
préférentiellement choisis quand il y a une ambiguïté. Dans la
catégorie des types utilisateurs, chaque type est son propre type
préféré. Les expressions ambiguës (celles avec de multiples
solutions d'analyse candidates) peuvent souvent être résolues quand
il y a de nombreux types pré-définis possibles mais elles
soulèveront une erreur quand il existe des choix multiples pour des
types utilisateurs.
Toutes les règles de conversions de types sont écrites en gardant à
l'esprit plusieurs principes :
-
Les conversions implicites ne doivent jamais avoir de
résultats surprenants ou imprévisibles.
-
Les types utilisateurs dont l'analyseur n'a pas à priori
connaissance, devraient être « plus
hauts » dans la hiérarchie des types. Dans les
expressions de types mixtes, les types natifs doivent
toujours être convertis en un type utilisateur (seulement si
la conversion est nécessaire bien sûr).
-
Les types utilisateurs ne sont pas liés. Actuellement,
PostgreSQL™ n'a pas
d'informations disponibles sur les relations entre les types,
autres que celles fournies par les heuristiques codées en dur
pour les types natifs et les relations implicites basées sur
les fonctions et les conversions disponibles.
-
Il n'y aura pas de surcharge depuis l'analyseur ou
l'exécuteur si une requête n'a pas besoin d'une conversion
implicite de types. C'est-à-dire que si une requête est bien
formulée et si les types sont déjà bien distinguables, alors
la requête devra s'exécuter sans perte de temps
supplémentaire et sans introduire à l'intérieur de celle-ci
des appels à des conversions implicites non nécessaires.
De plus, si une requête nécessite habituellement une
conversion implicite pour une fonction et si l'utilisateur
définit une nouvelle fonction avec les types des arguments
corrects, l'analyseur devrait utiliser cette nouvelle
fonction et ne fera plus des conversions implicites en
utilisant l'ancienne fonction.