PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 04/06/2009 10:41:48

Oops
Membre

[Paramètres fonctions] Passage par référence

Bonjour tout le monde,

Je suis actuellement en train de faire un portage de Oracle sur PostgreSQL cependant je me suis aperçu d'un problème assez gênant. En effet, la notion INOUT qui est présent sous PostgreSQL ne représente pas la même notion que celle d'ORACLE. Sur ORACLE, cela signifie qu'on passe le paramètre par référence. En d'autres termes, lors de l'appel de la fonction, on renseigne le paramètre avec une variable externe à la fonction. Cette variable peut être modifier par la fonction.Si tel est le cas, la variable n'aura plus la même valeur en sortant de la fonction.

Sur PostgreSQL, ceci est totalement différent. En effet, lorsque l'on passe un paramètre en E/S sur PostgreSQL, cela sert juste à éviter de déclarer une variable en entrée et une variable en sortie quand elles sont du même type.

Exemple :

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

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


Je post donc ce sujet afin de savoir si ce que j'ai dit précédemment est vrai. Si tel est le cas, quelles solutions sont envisageable pour palier à ce problème.

Hors ligne

#2 04/06/2009 10:45:27

gleu
Administrateur

Re : [Paramètres fonctions] Passage par référence

Je n'ai pas compris la question. Pourriez-vous donner un exemple de ce qui fonctionne sous Oracle et pas sous PostgreSQL en ce qui concerne un paramètre INOUT ?


Guillaume.

Hors ligne

#3 04/06/2009 11:14:11

Marc Cousin
Membre

Re : [Paramètres fonctions] Passage par référence

Un paramètre en INOUT n'est pas passé par référence. INOUT évite juste de déclarer la même valeur deux fois, une fois en IN et l'autre fois en OUT.
Et la déclaration de variable de type OUT remplace simplement la déclaration avec RETURNS. Donc il s'agit de recopie, dans les deux sens.


Marc.

Hors ligne

#4 04/06/2009 11:17:48

Oops
Membre

Re : [Paramètres fonctions] Passage par référence

Désolé Gleu si je me suis mal exprimé, je te donne un exemple Oracle.

Procédure ORACLE :

CREATE OR REPLACE FUNCTION TEST(A IN NUMBER, B IN OUT NUMBER)  RETURN NUMBER IS
    C NUMBER(3);
BEGIN
    B := A;
    C := A + B;
    RETURN C;
END;

  DECLARE
   A1 NUMBER(3) := 10;
   B1 NUMBER(3) := 20;
   C1 NUMBER(3)
BEGIN
   C1 := TEST(A1,B1);
   DBMS_OUTPUT.PUT_LINE(A1 || ' ' || B1 || ' ' || C1);
END;

Dans cette fonction, B est passé en entrée/sortie.En d'autres termes, lors de l'affichage de B1, B1 ne sera plus égale à 20 mais à A soit 10. Nous avons donc une variable B1 qui a été passé en paramètre de la fonction TEST et qui se retrouve modifier après son appel.

Maintenant, j'aimerais faire une traduction de cette procédure sous PostgreSQL. Comment ferez-tu?

J'ai cette solution :

CREATE OR REPLACE FUNCTION TEST(A IN INTEGER, B INOUT INTEGER,C OUT INTEGER)  RETURNS RECORD AS $$
BEGIN
    B := A;
    C := A + B;

END;
$$ language 'plpgsql';

Cependant le comportement n'est pas du tout le même que celui d'ORACLE puisque ma fonction au lieu de renvoyer 1 valeur soit la valeur de C, elle renvoie deux valeurs, la valeur de C et celle de B.Les concepts de INOUT et OUT ne sont pas les mêmes sur PostgreSQL. En effet, sous Oracle il suffit de mettre deux variables en entrée de la procédure et on récupère la valeur de C tout en ayant la variable B1 qui a été modifier durant la fonction. Sur PostgreSQL, on récupère la valeur de C et de B.

Sera t'il possible de renseigner le paramètre INOUT B de ma fonction avec une variable et si cela est possible est ce qu'après l'appel de la procédure ma variable aura été modifié?

Dernière modification par Oops (04/06/2009 11:19:14)

Hors ligne

#5 04/06/2009 11:34:32

Marc Cousin
Membre

Re : [Paramètres fonctions] Passage par référence

le OUT et INOUT ne sont  que des décorations syntaxiques qui permettent d'éviter de faire des return dans la fonction (ils récupèrent les dernières valeurs des paramètres OUT/INOUT et les retournent de façon transparente). Mais cela reste équivalent à un RETURN : les paramètres ne sont pas modifiés, et ne sont pas passés par référence mais par valeur.


Marc.

Hors ligne

#6 04/06/2009 11:48:23

Oops
Membre

Re : [Paramètres fonctions] Passage par référence

Merci beaucoup Marc,

C'est bien ce qu'il me semblait cependant, ca pose pas mal de problème pour le portage. Comment faire pour créer une fonction qui permettent de modifier une variable externe à la fonction. On va être obligatoirement obliger de modifier le source du programme qui s'appuie sur la fonction PostgreSQL traduite pour récupérer la valeur du paramètre en sortie de la fonction et l'assigner à la variable du programme. Si tu as des solutions, hesite pas à me les transmettre, merci beaucoup.Bonne journée.

Hors ligne

#7 04/06/2009 13:29:06

Marc Cousin
Membre

Re : [Paramètres fonctions] Passage par référence

Je ne pense pas qu'il y ait une méthode propre autre que la modification du code appelant. Même une bidouille entraînerait une modif de ce code, alors autant partir vers la version propre.

Mais bon, peut être quelqu'un d'autre aura une idée...


Marc.

Hors ligne

#8 04/06/2009 15:43:09

gleu
Administrateur

Re : [Paramètres fonctions] Passage par référence

Le seul moyen que je connaisse est d'utiliser les paramètres personnalisés. Comme les paramètres sont valables pour la session, ça peut fonctionner. Mais c'est loin d'être propre.


Guillaume.

Hors ligne

#9 04/06/2009 16:16:55

Marc Cousin
Membre

Re : [Paramètres fonctions] Passage par référence

Et puis même via les paramètres personnalisés, tu es toujours obligé de modifier le code en amont pour les utiliser à la place des variables non ?


Marc.

Hors ligne

#10 04/06/2009 18:13:25

gleu
Administrateur

Re : [Paramètres fonctions] Passage par référence

Oui, tout à fait. J'avais oublié ce « détail » smile


Guillaume.

Hors ligne

Pied de page des forums