PostgreSQL
La base de donnťes la plus sophistiquťe au monde.

Ouverture de session

Contactez-nous

Administration du site :
"equipe chez postgresqlfr point org"

Contact presse :
"fr chez postgresql point org"

Contact association :
"bureau chez postgresqlfr point org"

Questions PostgreSQL :
 IRC :
  serveur irc.freenode.net
  canal #postgresqlfr

Recherche

Accéder aux archives

« Octobre 2008  
Lun Mar Mer Jeu Ven Sam Dim
  2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31  

Syndication

Flux XML

Sondage

Quelle est la version de PostgreSQL la plus répandue sur vos serveurs ?
8.3
10%
8.2
42%
8.1
40%
8.0
2%
7.4
6%
7.3 ou antérieure
0%
Nombre de votes: 48

Langages de procédure : type OUT et INOUT

Technique | Langages de procédure : type OUT et INOUT

Par Guillaume Lelarge le 16/12/2005 - 00:59

Attention, tous les exemples de cet article utilisent le langage PL/pgsql. Pour l'utiliser, vous devez l'int√©grer √† votre base. Cela se fait tout simplement avec cette commande :

createlang plpgsql metier

Je viens donc d'intégrer le langage de procédures plpgsql dans la base metier.

Avant la version 8.1, PostgreSQL n'acceptait que des arguments en entr√©e dans la d√©claration des fonctions (et quelque soit le langage de proc√©dures utilis√©). Pour renvoyer un r√©sultat, il fallait passer par la ¬ę valeur de retour ¬Ľ. Malgr√© tout, il √©tait possible de renvoyer plusieurs valeurs en utilisant un type composite. En fait, cela revenait √† renvoyer une ligne de plusieurs colonnes d'une table ¬ę virtuelle ¬Ľ.

Cr√©ons une premi√®re fonction servant uniquement √† incr√©menter la valeur en entr√©e :

CREATE FUNCTION incremente(valeur int4) RETURNS int4 AS
$$
BEGIN
RETURN valeur + 1;
END
$$ LANGUAGE plpgsql;

¬ę RETURNS int4 ¬Ľ (sur la premi√®re ligne) indique le type de la valeur renvoy√©e (ici un entier, plus pr√©cis√©ment un int4). ¬ę RETURN ... ¬Ľ (4√® ligne) sert √† indiquer la valeur √† renvoyer. Voici les r√©sultats sur deux tests :

metier=# SELECT incremente(1);
incremente
------------
2
(1 ligne)

metier=# SELECT incremente(2);
incremente
------------
3
(1 ligne)

Cr√©ons maintenant une fonction renvoyant plusieurs valeurs. Nous devons passer par un type composite, √©quivalent d'une structure en C :

CREATE TYPE inc AS (
val1 int4,
val2 int4,
str varchar(10));

Une fois ce type d√©clar√©, nous pouvons passer √† la cr√©ation de la proc√©dure stock√©e :

CREATE FUNCTION incremente_2(valeur int4) RETURNS inc AS
$$
DECLARE
r inc;
BEGIN
SELECT INTO r valeur + 1, valeur + 2, 'test';
RETURN r;
END
$$ LANGUAGE plpgsql;

Comme pr√©c√©demment, ¬ę RETURNS ... ¬Ľ indique le type (composite dans ce cas) renvoy√© et ¬ę RETURN ... ¬Ľ indique la valeur renvoy√©e. Voici quelques exemples d'utilisation de la fonction :

metier=# SELECT incremente_2(5);
incremente
------------
(6,7,test)
(1 ligne)

metier=# SELECT (incremente_2(5)).val1;
val1
------
6
(1 ligne)

metier=# SELECT (incremente_2(5)).str;
str
------
test
(1 ligne)

La fonction utilise tous les concepts des types composites, ce qui en rend la gestion un peu lourde. Elle ne renvoie pas réellement une ligne d'un tableau mais un type ROW. De plus, elle oblige à créer un type séparément.

La version 8.1 apporte une solution √©l√©gante √† ce probl√®me gr√Ęce √† deux nouveaux types de param√®tres : un param√®tre en sortie seule (OUT) et un param√®tre en entr√©e/sortie (INOUT). Sans indication, un param√®tre est en entr√©e. Pour indiquer le type de param√®tre, il faut l'√©crire avant le nom de la variable et/ou son type de variable).

Commençons par le type OUT.

CREATE FUNCTION incremente81(IN int4, OUT int4) AS
$$
BEGIN
$2 = $1 + 1;
END;
LANGUAGE plpgsql;

Premier point int√©ressant, je n'ai pas indiqu√© de type en retour (avec l'√©lement RETURNS). Deuxi√®me point int√©ressant qui en d√©coule, il n'y a pas non plus d'instruction RETURN. La valeur renvoy√©e sera le seul param√®tre d√©clar√© en sortie, $2 dans cet exemple. Ex√©cutons cette fonction :

metier=# SELECT incremente81(5);
incremente81
----------------
6
(1 ligne)

Elle fonctionne exactement comme notre ancienne fonction ¬ę incremente ¬Ľ. Remarquez simplement que je n'ai indiqu√© qu'un seul param√®tre. Le param√®tre de type OUT ne peut pas √™tre fourni. Vous ne pouvez pas non plus y placer une variable comme dans le cas des fonctions avec param√®tres par r√©f√©rence dans des langages comme le C. Tous les param√®tres OUT et INOUT sont renvoy√©s comme valeur de retour. Continuons avec le type INOUT qui vous permet d'y stocker une valeur et de la r√©cup√©rer modifi√©e en sortie de la fonction.

CREATE FUNCTION incremente81(INOUT int4) AS
$$
BEGIN
$1 = $1 + 1;
END;
$$ LANGUAGE plpgsql;

Là aussi, pas de RETURNS et de RETURN.

metier=# SELECT incremente81(5);
incremente81
----------------
6
(1 ligne)

Ce type est surtout utile pour éviter de déclarer une variable en entrée et une variable en sortie quand elles sont du même type.

Pour en revenir √† notre exemple complexe o√Ļ plusieurs valeurs sont renvoy√©es par une seule fonction, voici comment elle s'√©crirait avec cette nouvelle fonctionnalit√© :

CREATE FUNCTION incremente81_2(IN valeur int4, OUT val1 int4, OUT val2 int4, OUT str varchar(10)) AS
$$
BEGIN
val1 = valeur + 1;
val2 = valeur + 2;
str = 'test';
END
$$ LANGUAGE plpgsql;

Pas de d√©claration d'un type composite, pas de RETURNS et de RETURN : la valeur renvoy√©e et son type d√©pendent du nombre d'arguments d√©clar√©s en sortie (donc OUT et INOUT). Remarquez aussi que je n'indique rien pour les param√®tres OUT. S'il y a plusieurs arguments, l'√©l√©ment renvoy√© sera de type composite. Si les arguments sont nomm√©s comme dans l'exemple ci-dessus, il sera possible d'acc√©der √† chaque √©l√©ment :

metier=# SELECT incremente81_2(5);
incremente
------------
(6,7,test)
(1 ligne)

metier=# SELECT (incremente81_2(5)).val1;
val1
------
6
(1 ligne)

metier=# SELECT (incremente81_2(5)).str;
str
------
test
(1 ligne)

L'écriture de la fonction est plus intuitive, sa compréhension est plus simple (par exemple, il n'est plus nécessaire de savoir ce que représente le type inc).

Cette fonctionnalit√© a aussi √©t√© ajout√©e pour faciliter le passage d'Oracle vers PostgreSQL. Oracle propose aussi ce type d'arguments. Il propose en plus le passage de variables par r√©f√©rence, ce que PostgreSQL ne fait pas (encore ?).

© PostgreSQLFr, tous droits r√©serv√©s.
Site déclaré à la CNIL sous le numéro 1074678, conformément à la Loi en vigueur.