8.11. Types composites

Un type composite d�crit la structure d'une ligne ou d'un enregistrement ; il est en essence une simple liste de noms de champs et de leur types de donn�es. PostgreSQL autorise l'utilisation de valeurs de types composite identiques de plusieurs fa�ons � l'utilisation des types simples. Par exemple, une colonne d'une table peut �tre d�clar�e comme �tant de type composite.

8.11.1. D�claration de types composite

Voici deux exemples simples de d�finition de types composite :

CREATE TYPE complexe AS (
    r       double precision,
    i       double precision
);

CREATE TYPE element_inventaire AS (
    nom             text,
    id_fournisseur  integer,
    prix            numeric
);

La syntaxe est comparable � CREATE TABLE sauf que seuls les noms de champs et leur types peuvent �tre sp�cifi�s ; aucune contrainte (telle que NOT NULL) ne peut �tre inclus actuellement. Notez que le mot cl� AS est essentiel ; sans lui, le syst�me penserait � un autre genre de commande CREATE TYPE et vous obtiendriez d'�tranges erreurs de syntaxe.

Apr�s avoir d�fini les types, nous pouvons les utiliser pour cr�er des tables :

CREATE TABLE disponible (
    element   element_inventaire,
    nombre    integer
);

INSERT INTO disponible VALUES (ROW('fuzzy dice', 42, 1.99), 1000);

ou des fonctions :

CREATE FUNCTION prix_extension(element_inventaire, integer) RETURNS numeric
AS 'SELECT $1.prix * $2' LANGUAGE SQL;

SELECT prix_extension(element, 10) FROM disponible;

Quand vous cr�ez une table, un type composite est automatiquement cr��, avec le m�me nom que la table, pour repr�senter le type de ligne de la table. Par exemple, si nous avions dit

CREATE TABLE element_inventaire (
    nom             text,
    id_fournisseur  integer REFERENCES fournisseur,
    prix            numeric CHECK (prix > 0)
);

alors le m�me type composite element_inventaire montr� ci-dessus aurait �t� cr�� et pourrait �tre utilis� comme ci-dessus. N�anmoins, notez une restriction importante de l'impl�mentation actuelle : comme aucune contrainte n'est associ�e avec un type composite, les contraintes indiqu�es dans la d�finition de la table ne sont pas appliqu�es aux valeurs du type composite en dehors de la table. (Un contournement partiel est d'utiliser les types de domaine comme membres de types composites.)

8.11.2. Entr�e d'une valeur composite

Pour �crire une valeur composite comme une constante litt�rale, englobez les valeurs du champ dans des parenth�ses et s�parez-les par des virgules. Vous pouvez placer des guillemets doubles autour de chaque valeur de champ et vous devez le faire si elle contient des virgules ou des parenth�ses. (Plus de d�tails ci-dessous). Donc, le format g�n�ral d'une constante composite est le suivant :

'( val1 , val2 , ... )'

Voici un exemple

'("fuzzy dice",42,1.99)'

qui serait une valeur valide du type element_inventaire d�fini ci-dessus. Pour rendre un champ NULL, n'�crivez aucun caract�re dans sa position dans la liste. Par exemple, cette constante sp�cifie un troisi�me champ NULL :

'("fuzzy dice",42,)'

Si vous voulez un champ vide au lieu d'une valeur NULL, saisissez deux guillemets :

'("",42,)'

Ici, le premier champ est une cha�ne vide non NULL alors que le troisi�me est NULL.

(Ces constantes sont r�ellement seulement un cas sp�cial de constantes g�n�riques de type discut�es dans Section 4.1.2.5. La constante est initialement trait�e comme une cha�ne et pass�e � la routine de conversion de l'entr�e de type composite. Une sp�cification explicite de type pourrait �tre n�cessaire.)

La syntaxe d'expression ROW pourrait aussi �tre utilis�e pour construire des valeurs composites. Dans la plupart des cas, ceci est consid�rablement plus simple � utiliser que la syntaxe de cha�ne litt�rale car vous n'avez pas � vous inqui�ter des multiples couches de guillemets. Nous avons d�j� utilis� cette m�thode ci-dessus :

ROW('fuzzy dice', 42, 1.99)
ROW('', 42, NULL)

Le mot cl� ROW est optionnel si vous avez plus d'un champ dans l'expression, donc ceci peut �tre simplifi� avec

('fuzzy dice', 42, 1.99)
('', 42, NULL)

La syntaxe de l'expression ROW est discut�e avec plus de d�tails dans Section 4.2.11.

8.11.3. Acc�der aux types composite

Pour acc�der � un champ d'une colonne composite, vous pouvez �crire un point et le nom du champ, un peu comme la s�lection d'un champ � partir d'un nom de table. En fait, c'est tellement similaire que vous pouvez souvent utiliser des parenth�ses pour �viter une confusion de l'analyseur. Par exemple, vous pouvez essayer de s�lectionner des sous-champs � partir de notre exemple de table, disponible, avec quelque chose comme :

SELECT element.nom FROM disponible WHERE element.prix > 9.99;

Ceci ne fonctionnera pas car le nom element est pris pour le nom d'une table, et non pas d'un champ, suivant les r�gles de la syntaxe SQL. Vous devez l'�crire ainsi :

SELECT (element).nom FROM disponible WHERE (element).prix > 9.99;

ou si vous avez aussi besoin d'utiliser le nom de la table (par exemple dans une requ�te multi-table), de cette fa�on :

SELECT (disponible.element).nom FROM disponible WHERE (disponible.element).prix > 9.99;

Maintenant, l'objet entre parenth�ses est correctement interpr�t� comme une r�f�rence � la colonne element, puis le sous-champ peut �tre s�lectionn� � partir de lui.

Des probl�mes syntaxiques similaires s'appliquent quand vous s�lectionnez un champ � partir d'une valeur composite. En fait, pour s�lectionner un seul champ � partir du r�sultat d'une fonction renvoyant une valeur composite, vous aurez besoin d'�crire quelque chose comme

SELECT (ma_fonction(...)).champ FROM ...

Sans les parenth�ses suppl�mentaires, ceci provoquera une erreur.

8.11.4. Modifier les types composite

Voici quelques exemples de la bonne syntaxe pour ins�rer et mettre � jour des colonnes composites. Tout d'abord pour ins�rer ou modifier une colonne enti�re :

INSERT INTO matab (col_complexe) VALUES((1.1,2.2));

UPDATE matab SET col_complexe = ROW(1.1,2.2) WHERE ...;

Le premier exemple omet ROW, le deuxi�me l'utilise ; nous pouvons le faire des deux fa�ons.

Nous pouvons mettre � jour un sous-champ individuel d'une colonne composite :

UPDATE matab SET col_complexe.r = (col_complexe).r + 1 WHERE ...;

Notez ici que nous n'avons pas besoin de (et, en fait, ne pouvons pas) placer des parenth�ses autour des noms de colonnes apparaissant juste apr�s SET, mais nous avons besoin de parenth�ses lors de la r�f�rence � la m�me colonne dans l'expression � droite du signe d'�galit�.

Et nous pouvons aussi sp�cifier des sous-champs comme cibles de la commande INSERT :

INSERT INTO matab (col_complexe.r, col_complexe.i) VALUES(1.1, 2.2);

Si tous les sous-champs d'une colonne ne sont pas sp�cifi�s, ils sont remplis avec une valeur NULL.

8.11.5. Syntaxe en entr�e et sortie d'un type composite

La repr�sentation texte externe d'une valeur composite consiste en des �l�ments qui sont interpr�t�s suivant les r�gles de conversion d'entr�es/sorties pour les types de champs individuels, plus des d�corations indiquant la structure composite. Cette d�coration consiste en des parenth�ses (( et )) autour de la valeur enti�re ainsi que des virgules (,) entre les �l�ments adjacents. Des espace blancs en dehors des parenth�ses sont ignor�s mais � l'int�rieur des parenth�ses, ils sont consid�r�s comme faisant partie de la valeur du champ et pourrait ou non �tre significatif suivant les r�gles de conversion de l'entr�e pour le type de donn�es du champ. Par exemple, dans

'(  42)'

l'espace blanc sera ignor� si le type du champ est un entier, mais pas s'il s'agit d'un champ de type texte.

Comme indiqu� pr�c�demment, lors de l'�criture d'une valeur composite, vous pouvez saisir des guillemets doubles autour de chaque valeur de champ individuel. Vous devez le faire si la valeur du champ pourrait sinon g�ner l'analyseur de la valeur du champ composite. En particulier, les champs contenant des parenth�ses, des virgules, des guillemets doubles ou des antislashs doivent �tre entre guillemets doubles. Pour placer un guillemet double ou un antislash dans la valeur d'un champ composite entre guillemets, faites-le pr�c�der d'un antislash. (De plus, une paire de guillemets doubles � l'int�rieur d'une valeur de champ � guillemets doubles est pris pour repr�senter un caract�re guillemet double, en analogie aux r�gles des guillemets simples dans les cha�nes SQL litt�rales.) Autrement, vous pouvez utiliser l'�chappement par antislash pour prot�ger tous les caract�res de donn�es qui auraient �t� pris pour une syntaxe composite.

Une valeur de champ composite vide (aucun caract�re entre les virgules ou parenth�ses) repr�sente une valeur NULL. Pour �crire une valeur qui est une cha�ne vide plut�t qu'une valeur NULL, �crivez "".

La routine de sortie composite placera des guillemets doubles autour des valeurs de champs s'ils sont des cha�nes vides ou s'ils contiennent des parenth�ses, virgules, guillemets doubles, antislash ou espaces blancs. (Faire ainsi pour les espaces blancs n'est pas essentiel mais aide � la lecture.) Les guillemets doubles et antislashs dans les valeurs des champs seront doubl�s.

Note�: Rappelez-vous que ce que vous allez saisir dans une commande SQL sera tout d'abord interpr�t� comme une cha�ne litt�rale, puis comme un composite. Ceci double le nombre d'antislash dont vous avez besoin. Par exemple, pour ins�rer un champ text contenant un guillemet double et un antislash dans une valeur composite, vous devez �crire

INSERT ... VALUES ('("\\"\\\\")');

Le processeur des cha�nes litt�rales supprime un niveau d'antislash de fa�on � ce qui arrive � l'analyseur de valeurs composites ressemble � ("\"\\"). � son tour, la cha�ne remplie par la routine d'entr�e du type de donn�es text devient "\. (Si nous �tions en train de travailler avec un type de donn�es dont la routine d'entr�e traite aussi les antislashs sp�cialement, bytea par exemple, nous pourrions avoir besoin d'au plus huit antislashs dans la commande pour obtenir un antislash dans le champ composite stock�.) Le guillemet dollar (voir Section 4.1.2.2) pourrait �tre utilis� pour �viter le besoin des antislashs doubl�s.

Astuce�: La syntaxe du constructeur ROW est habituellement plus simple � utiliser que la syntaxe du litt�rale composite lors de l'�criture de valeurs composites dans des commandes SQL. Dans ROW, les valeurs individuelles d'un champ sont �crits de la m�me fa�on qu'ils l'auraient �t� en �tant pas membres du composite.