Documentation PostgreSQL 8.0.25 | ||||
---|---|---|---|---|
Pr�c�dent | Arri�re rapide | Chapitre 31. Extension de SQL | Avance rapide | Suivant |
D�crit dans la Section 31.2, PostgreSQL peut �tre �tendu pour supporter de nouveaux types de donn�es. Cette section d�crit comment d�finir de nouveaux types de base, qui sont des types de donn�es d�finis en-dessous du niveau du langage SQL. Cr�er un nouveau type de base requiert l'impl�mentation de fonctions pour op�rer sur le type dans un langage de base du niveau du C.
Les exemples de cette section sont disponibles dans complex.sql et complex.c du r�pertoire src/tutorial de la distribution des sources. Voir le fichier README de ce r�pertoire pour les instructions d'ex�cution des exemples.
Un type d�fini par l'utilisateur doit toujours avoir des fonctions d'entr�e et de sortie. Ces fonctions d�terminent comment le type appara�t dans les cha�nes de caract�res (pour l'entr�e par l'utilisateur et le renvoi � l'utilisateur) et comment ce type est organis� en m�moire. La fonction d'entr�e prend comme argument une cha�ne de caract�res termin�e par NULL et renvoie la repr�sentation interne (en m�moire) du type. La fonction de sortie prend comme argument la repr�sentation interne du type et renvoie une cha�ne de caract�res termin�e par NULL. Si vous voulez faire plus avec le type que simplement l'enregistrer, vous devez apporter des fonctions suppl�mentaires pour impl�menter toutes op�rations que vous souhaitez avoir pour ce type.
Supposons que nous voulions d�finir un type complex repr�sentant les nombres complexes. Une fa�on naturelle de repr�senter un nombre complexe en m�moire serait la structure C suivante :
typedef struct Complex { double x; double y; } Complex;
Nous aurons besoin d'utiliser ce type par r�f�rence car il est trop important pour tenir sur une seule valeur Datum.
Comme repr�sentation externe du type sous forme de cha�ne, nous choisissons une cha�ne de la forme (x,y).
Habituellement, les fonctions d'entr�e et de sortie ne sont pas compliqu�es � �crire, surtout la fonction de sortie. Mais en d�finissant la repr�sentation externe du type par une cha�ne, souvenez-vous que vous devez �ventuellement �crire un analyseur complet et robuste pour cette repr�sentation en tant que fonction d'entr�e. Par exemple :
PG_FUNCTION_INFO_V1(complex_in); Datum complex_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); double x, y; Complex *result; if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for complex: \"%s\"", str))); result = (Complex *) palloc(sizeof(Complex)); result->x = x; result->y = y; PG_RETURN_POINTER(result); }
La fonction de sortie peut simplement s'�crire :
PG_FUNCTION_INFO_V1(complex_out); Datum complex_out(PG_FUNCTION_ARGS) { Complex *complex = (Complex *) PG_GETARG_POINTER(0); char *result; result = (char *) palloc(100); snprintf(result, 100, "(%g,%g)", complex->x, complex->y); PG_RETURN_CSTRING(result); }
Vous devriez faire attention en �crivant des fonctions d'entr�e et de sortie inverses l'une de l'autre. Sinon, vous aurez de graves probl�mes quand vous aurez besoin de sauvegarder votre base de donn�es dans un fichier et ensuite de le relire. Ceci est un probl�me particuli�rement fr�quent quand des nombres � virgule flottante sont concern�s.
De mani�re optionnelle, un type d�fini par l'utilisateur peut apporter des routines d'entr�e et de sortie binaires. Les entr�es/sorties binaires sont normalement plus rapides mais moins portables que les entr�es/sorties textuelles. Avec les entr�es/sorties textuelles, c'est � vous de d�finir exactement la repr�sentation binaire externe. La plupart des types de donn�es int�gr�s essaient d'apporter une repr�sentation binaire ind�pendante de la machine. Pour complex, nous allons revenir aux convertisseurs d'entr�es/sorties binaires pour le type float8 :
PG_FUNCTION_INFO_V1(complex_recv); Datum complex_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Complex *result; result = (Complex *) palloc(sizeof(Complex)); result->x = pq_getmsgfloat8(buf); result->y = pq_getmsgfloat8(buf); PG_RETURN_POINTER(result); } PG_FUNCTION_INFO_V1(complex_send); Datum complex_send(PG_FUNCTION_ARGS) { Complex *complex = (Complex *) PG_GETARG_POINTER(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, complex->x); pq_sendfloat8(&buf, complex->y); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Pour d�finir le type complex, nous avons besoin de cr�er les fonctions d'entr�es/sorties d�finies par l'utilisateur avant de cr�er le type :
CREATE FUNCTION complex_in(cstring) RETURNS complex AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_out(complex) RETURNS cstring AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_recv(internal) RETURNS complex AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_send(complex) RETURNS bytea AS 'filename' LANGUAGE C IMMUTABLE STRICT;
Notez que la d�claration des fonctions d'entr�e et de sortie doit pouvoir r�f�rencer un type non encore d�fini. Ceci est permis mais provoque des messages d'avertissement qui peuvent �tre ignor�s. La fonction en entr�e doit d'abord appara�tre.
Finalement, nous pouvons d�clarer le type de donn�es :
CREATE TYPE complex ( internallength = 16, input = complex_in, output = complex_out, receive = complex_recv, send = complex_send, alignment = double );
Quand vous d�finissez un nouveau type de base, PostgreSQL fournit automatiquement le support pour des tableaux de ce type. Pour des raisons historiques, le type tableau a le m�me nom que le type de base avec un caract�re soulign� (_) en pr�fixe.
Une fois que le type de donn�es existe, nous pouvons d�clarer les fonctions suppl�mentaires pour apporter des op�rations utiles pour ce type de donn�es. Les op�rateurs peuvent alors �tre d�finis au-dessus de ces fonctions et, si n�cessaire, les classes d'op�rateurs peuvent aussi �tre cr��es pour apporter le support de l'indexage du type de donn�es. Ces couches suppl�mentaires sont discut�es dans les sections suivantes.
Si les valeurs de votre type de donn�e peuvent exc�der une taille de quelques
centaines d'octets (sous la forme interne), vous devriez marquer le type de
donn�es comme TOAST-able. Pour cela, la
repr�sentation interne doit suivre le cadre standard des donn�es � longueur
variable : les quatre premiers octets doivent �tre un int32
contenant la longueur totale en octets de la donn�e (lui-m�me inclus). Les
fonctions C op�rant sur le type de donn�es doivent faire bien attention �
d�baller toutes les valeurs toast des donn�es (ce d�tail peut normalement �tre
cach�e dans les macros GETARG
). Puis, quand on ex�cute
la commande CREATE TYPE, sp�cifiez la longueur interne
comme variable et choisissez l'option de stockage en m�moire
appropri�e.
Pour plus de d�tails, voir la description de la commande CREATE TYPE.
Pr�c�dent | Sommaire | Suivant |
Agr�gats d�finis par l'utilisateur | Niveau sup�rieur | Op�rateurs d�finis par l'utilisateur |