Documentation PostgreSQL 8.3.23 > Référence > Commandes SQL > CREATE CAST | |
CREATE AGGREGATE | CREATE CONSTRAINT TRIGGER |
CREATE CAST (typesource AS typecible) WITH FUNCTION nomfonction (argtype) [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (typesource AS typecible) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST définit un transtypage. Un transtypage spécifie l'opération de conversion entre deux types de données. Par exemple :
SELECT CAST(42 AS float8);
convertit la constante entière 42 en float8 en appelant une fonction précédemment définie, float8(int4) dans le cas présent (si aucun transtypage convenable n'a été défini, la conversion échoue).
Deux types peuvent être binairement compatibles, ce qui signifie que la conversion d'un type en l'autre est « gratuite » et ne nécessite pas d'appel de fonction. Les valeurs correspondantes doivent pour cela utiliser la même représentation interne. Les types text et varchar, par exemple, sont binairement compatibles.
Un transtypage peut être appelé explicitement. Par exemple : CAST(x AS nomtype) ou x::nomtype.
Si le transtypage est marqué AS ASSIGNMENT (NDT : à l'affectation), alors son appel peut être implicite lors de l'affectation d'une valeur à une colonne du type de donnée cible. Par exemple, en supposant que foo.f1 soit une colonne de type text :
INSERT INTO foo (f1) VALUES (42);
est autorisé si la conversion du type integer vers le type text est indiquée AS ASSIGNMENT. Dans le cas contraire, c'est interdit. Le terme de transtypage d'affectation est utilisé pour décrire ce type de conversion.
Si la conversion est marquée AS IMPLICIT, alors elle peut être appelée implicitement dans tout contexte, soit par une affectation soit en interne dans une expression (nous utilisons généralement le terme conversion implicite pour décrire ce type de conversion.) Par exemple, voici une requête :
SELECT 2 + 4.0;
L'analyseur marque au début les constantes comme étant de type integer et numeric respectivement. Il n'existe pas d'opérateur integer + numeric dans les catalogues systèmes mais il existe un opérateur numeric + numeric. La requête sera un succès si une conversion de integer vers numeric est disponible et marquée AS IMPLICIT -- ce qui est le cas. L'analyseur appliquera la conversion implicite et résoudra la requête comme si elle avait été écrite de cette façon :
SELECT CAST ( 2 AS numeric ) + 4.0;
Maintenant, les catalogues fournissent aussi une conversion de numeric vers integer. Si cette conversion était marquée AS IMPLICIT -- mais ce n'est pas le cas -- alors l'analyseur devra choisir entre l'interprétation ci-dessus et son alternative (la conversion de la constante numeric en un integer) et appliquer l'opérateur integer + integer. Comme il n'a aucune information qui lui permettrait de choisir le meilleur moyen, il abandonne et déclare la requête comme étant ambigüe. Le fait qu'une seule des conversions est indiquée comme implicite est le moyen par lequel nous apprenons à l'analyseur de préférer la première solution (c'est-à-dire de transformer une expression numeric-and-integer en numeric) ; il n'y a pas d'autre moyen.
Il est conseillé d'être conservateur sur le marquage du caractère implicite des transtypages. Une surabondance de transtypages implicites peut conduire PostgreSQL™ à interpréter étrangement des commandes, voire à se retrouver dans l'incapacité totale de les résoudre parce que plusieurs interprétations s'avèrent envisageables. Une bonne règle est de ne réaliser des transtypages implicites que pour les transformations entre types de la même catégorie générale et qui préservent l'information. Par exemple, la conversion entre int2 et int4 peut être raisonnablement implicite mais celle entre float8 et int4 est probablement réservée à l'affectation. Les transtypages inter-catégories, tels que de text vers int4, sont préférablement exécutés dans le seul mode explicite.
Pour créer un transtypage, il faut être propriétaire du type source ou destination. Seul le superutilisateur peut créer un transtypage binairement compatible (une erreur sur un tel transtypage peut aisément engendrer un arrêt brutal du serveur).
Le nom du type de donnée source du transtypage.
Le nom du type de donnée cible du transtypage.
La fonction utilisée pour effectuer la conversion. Le nom de la fonction peut être qualifié du nom du schéma. Si ce n'est pas le cas, la fonction est recherchée dans le chemin des schémas. Le type de données résultant de la fonction doit correspondre au type cible du transtypage. Ses arguments sont explicités ci-dessous.
Indication d'une compatibilité binaire des types source et cible. Aucune fonction n'est ainsi requise pour effectuer la conversion.
Lors d'une affectation, l'invocation du transtypage peut être implicite.
L'invocation du transtypage peut être implicite dans tout contexte.
Les fonctions de transtypage ont un à trois arguments. Le premier argument est du même type que le type source. Le deuxième argument, si fourni, doit être de type integer. Il stocke le modificateur de type associé au type de destination, ou -1 en l'absence de modificateur. Le troisième argument, si fourni, doit être de type boolean. Il vaut true si la conversion est explicite, false dans le cas contraire. Bizarrement, les spécifications SQL appellent des comportements différents pour les transtypages explicites et implicites dans certains cas. Ce paramètre est fourni pour les fonctions qui implémentent de tel transtypages. Il n'est pas recommandé de concevoir des types de données utilisateur entrant dans ce cas de figure.
En général, un transtypage correspond à des type source et destination différents. Cependant, il est permis de déclarer un transtypage entre types source et destination identiques si la fonction de transtypage a plus d'un argument. Cette possibilité est utilisée pour représenter dans le catalogue système des fonctions de transtypage agissant sur la longueur d'un type. La fonction nommée est utilisée pour convertir la valeur d'un type à la valeur du modificateur de type fournie par le second argument.
Quand un transtypage concerne des types source et destination différents et que la fonction a plus d'un argument, le transtypage et la conversion de longeur du type destination sont faites en une seule etape. Quand une telle entrée n'est pas disponible, le transtypage vers un type qui utilise un modificateur de type implique deux étapes, une pour convertir les types de données et la seconde pour appliquer le modificateur.
DROP CAST est utilisé pour supprimer les transtypages utilisateur.
Pour convertir les types dans les deux sens, il est obligatoire de déclarer explicitement les deux sens.
Il est habituellement nécessaire de créer des conversions entre des types définis par l'utilisateur et des types de chaîne standards (text, varchar etchar(n)). PostgreSQL™ gèrera automatiquement une conversion vers un type chaîne à l'appel d'une autre fonction en sortie d'un type ou gèrera une conversion vers un type chaîne en appelent l'autre fonction en entrée du type. Ces conversions automatiques sont connues sous le nom de conversions I/O. Ces conversions vers des types chaîne sont traitées comme des conversions d'affectation, alors que ces conversions à partir de type chaîne sont seulement explicites. Vous pouvez changer ce comportement en déclarant votre propre conversion pour rempalcer une conversion I/O mais, habituellement, la seule raison de le faire est si vous voulez que la conversion soit plus facilement appelable que la forme standard de conversion par affectation ou le paramètre pour ue conversion explicite seulement. Une autre raison possible est que vous voulez que la conversion se comporte différement de la fonction I/O du type ; mais c'est suffisamment surprenant pour que vous y pensiez à deux fois avant de le faire. (Un petit nombre de types internes ont en fait des comportements différents pour les conversions, principalement à cause des besoins du standard SQL.)
Avant PostgreSQL™ 7.3, toute fonction qui portait le même nom qu'un type de données, retournait ce type de données et prenait un argument d'un autre type était automatiquement détectée comme une fonction de conversion. Cette convention a été abandonnée du fait de l'introduction des schémas et pour pouvoir représenter des conversions binairement compatibles dans les catalogues système. Les fonctions de conversion intégrées suivent toujours le même schéma de nommage mais elle doivent également être présentées comme fonctions de transtypage dans le catalogue système pg_cast.
Bien que cela ne soit pas requis, il est recommandé de suivre l'ancienne convention de nommage des fonctions de transtypage en fonction du type de données de destination. Beaucoup d'utilisateurs sont habitués à convertir des types de données à l'aide d'une notation de style fonction, c'est-à-dire nom_type(x). En fait, cette notation n'est ni plus ni moins qu'un appel à la fonction d'implantation du transtypage ; sa gestion n'est pas spécifique à un transtypage. Le non-respect de cette convention peut surprendre certains utilisateurs. Puisque PostgreSQL™ permet de surcharger un même nom de fonction avec différents types d'argument, il n'y a aucune difficulté à avoir plusieurs fonctions de conversion vers des types différents qui utilisent toutes le même nom de type destination.
En fait, le paragraphe précédent est une sur-simplification : il existe deux cas pour lesquels une construction d'appel de fonction sera traitée comme une demande de conversion sans qu'il y ait correspondance avec une fonction réelle. Si un appel de fonction nom(x) ne correspond pas exactement à une fonction existante, mais que nom est le nom d'un type de données et que pg_cast fournit une conversion compatible binairement vers ce type à partir du type x, alors l'appel sera construit à partir de la conversion compatible binairement. Cette exception est faite pour que les conversions compatibles binairement puissent être appelées en utilisant la syntaxe fonctionnelle, même si la fonction manque. De ce fait, s'il n'y pas d'entrée dans pg_cast mais que la conversion serait à partir de ou vers un type chapîne, l'appel sera réalisé avec une conversion I/O. Cette exception autorise l'appel de conversion I/O en utilisant la syntaxe fonctionnelle.
Création d'un transtypage du type bigint vers le type int4 à l'aide de la fonction int4(bigint) :
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
(Ce transtypage est déjà prédéfini dans le système.)