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

#1 06/07/2011 09:52:47

yo_haha
Membre

Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Bonjour,

J'ai une fonction retournant SET OF RECORD comme valeur de retour. Lorsque j'appelle cette fonction : SELECT * FROM ma_fonction(), j'ai une erreur : ERREUR:  indice du tableau en dehors de l'échelle. Dans la fonction j'utilise un tableau à deux dimensions de type VARCHAR[][] que j'utilise sans initialisation préalable parce que je ne connais pas le nombre de colonnes ni de lignes (ces nombres sont les résultats d'une requête SQL).

Est-ce que l'erreur vient de là ?

Cordialement.

Hors ligne

#2 06/07/2011 10:42:27

gleu
Administrateur

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Possible. Difficile à dire sans voir le code de la fonction.


Guillaume.

Hors ligne

#3 06/07/2011 11:00:07

yo_haha
Membre

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

La fonction :

/*La fonction retourne un tableau croisé de tous les sondages dans la première ligne et toutes
les couches litho dans la première colonne. Dans les autres cellules elle met la profondeur de
la couche litho de la même colonne dans le sondage de la même ligne */
DROP FUNCTION litho_sondage();
CREATE OR REPLACE FUNCTION litho_sondage() RETURNS SETOF text AS $$

DECLARE
    i INTEGER := 2;
    j INTEGER := 2;
    tailleSond INTEGER := 0;
    tailleLitho INTEGER := 0;
    trouve INTEGER := 0;
    found1 INTEGER := 0;
    found2 INTEGER := 0;
    ligne RECORD;
    tab RECORD;
    tableau VARCHAR[];
    elem VARCHAR;

    numsond CURSOR FOR SELECT num_sondage FROM sondage;

    nomlitho CURSOR FOR SELECT nom_litho FROM lithostratigraphie;

    resultat CURSOR FOR SELECT num_sondage, code_sondage, num_litho, nom_litho, toit_form_prof
                FROM sondage, litho, litho_sondage
                WHERE num_sondage=sondage AND num_litho=litho;

BEGIN
    tableau[1][1] := 'Litho/Sondage';

    --Remplissage de la première colonne par les nom des couches litho
    OPEN nomlitho;
    LOOP
        FETCH nomlitho INTO ligne;
        EXIT WHEN NOT FOUND;
        tableau[i][1] = ligne.nom_litho;
        i := i+1;
    END LOOP;
    CLOSE nomlitho;

    --Remplissage de la première ligne par les numéros des sondages
    i := 2;
    OPEN numsond;
    LOOP
        FETCH numsond INTO ligne;
        EXIT WHEN NOT FOUND;
        tableau[1][i] = ligne.code_sond;
        i := i+1;
    END LOOP;
    CLOSE numsond;

    --Remplissage des autres cellules par les profondeurs
    i := 2;
    OPEN resultat;
    LOOP
        FETCH resultat INTO ligne;
        EXIT WHEN NOT FOUND;
       
        --Recherche du sondage correspondant à la ligne résultat de la requête SQL
        LOOP
            IF tableau[i][1] = ligne.num_sondage THEN
                FOUND1 := 1;
            END IF;
            EXIT WHEN FOUND1 = 1;
   
            i := i+1;
           
        END LOOP;
   
        FOUND1 := 0;

        --Recherche de la couche litho correspondant à la ligne résultat de la requête SQL
        LOOP
            IF tableau[1][j] = ligne.nom_litho THEN
                FOUND2 := 1;
            END IF;
           
            EXIT WHEN FOUND2 = 1;

            j := j+1;
           
        END LOOP;

        FOUND2 := 0;

        --Remplissage de la cellule (i,j)
        tableau[i][j] := ligne.toit_form_prof;

        i := 2;
        j := 2;

    END LOOP;
    CLOSE resultat;

    j := 1;

    --Elimination des lignes dont les cellules sont nulles : Elimination des couches litho n'apparaissant dans aucun sondage
    FOR tab IN SELECT unnest(tableau) LOOP
        --La première ligne du tableau contient les noms des sondages, on passe aux suivantes
        IF j = 1 THEN
            j := j+1;
            CONTINUE;
        END IF;
       
        i := 1;
       
        FOR elem IN SELECT unnest(tab) LOOP
            --La première colonne du tableau contient les noms des couches litho, on passe aux suivantes
            IF i = 1 THEN
                i := i+1;
                CONTINUE;
            ELSIF elem IS NOT NULL THEN
                trouve := 1;
            END IF;

            --Si la ligne contient au moins une case non nulle, elle est gardée et on passe à la ligne suivante
            IF trouve = 1 THEN
                RETURN NEXT tab;
                EXIT;
            END IF;

        END LOOP;
       
    END LOOP;
   
    RETURN;
END;

$$ LANGUAGE 'plpgsql';



J'exécute la fonction de cette façon :

SELECT * FROM litho_sondage()

Hors ligne

#4 06/07/2011 22:43:56

gleu
Administrateur

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Et l'erreur survient sur quelle ligne de cette procédure ?


Guillaume.

Hors ligne

#5 07/07/2011 09:31:56

yo_haha
Membre

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

L'erreur apparaît lorssque j'exécute la requête suivante :
SELECT * FROM litho_sondage()

Voici le message d'erreur :

RREUR:  indice du tableau en dehors de l'échelle
CONTEXT:  PL/pgSQL function "litho_sondage" line 43 at affectation

********** Erreur **********

ERREUR: indice du tableau en dehors de l'échelle
État SQL :2202E
Contexte : PL/pgSQL function "litho_sondage" line 43 at affectation

Dernière modification par yo_haha (07/07/2011 09:47:22)

Hors ligne

#6 07/07/2011 11:20:53

daamien
damien clochard

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

L'erreur se trouve au niveau de la matrice tableau[i][j].  Vous ne pouvez pas faire grandir dynamiquement un tableau multi-dimensionnel. Ce qui fonctionne pour un tableau simple ne marche pas si vous ajouter un deuxième axe.

Il existe des solutions de contournement :

  * vous pouvez tenter de fixer la taille du tableau à l'avance
  * faire un pseudo-tableau 2D dans un tableau 1D

Le lien ci-dessous est assez complet. c'est en espagnol mais le code est universel smile

http://wiki.postgresql.org/wiki/Matrice … _funciones

Hors ligne

#7 07/07/2011 12:54:54

yo_haha
Membre

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Est-ce possible de remplecer tableau VARCHAR[][] par
                     taille_litho INTEGER;
    SELECT INTO taille_litho count(num_litho) FROM lithostratigraphie;

    taille_sond INTEGER;
    SELECT INTO taille_sond count(num_sond) FROM sondage;

    tableau VARCHAR[taille_litho][taille_sond];
    elem VARCHAR;

Hors ligne

#8 07/07/2011 22:12:48

gleu
Administrateur

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Non, ce n'est pas possible. Toutes les déclarations se font dans la partie DECLARE en tout début. De plus, il n'est pas possible d'utiliser des variables comme indice de tableau dans la partie DECLARE.


Guillaume.

Hors ligne

#9 08/07/2011 09:16:03

yo_haha
Membre

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Donc ce n'est nonplus possible de passer la taille du tableau en argument de la fonction ?

Hors ligne

#10 08/07/2011 09:32:35

gleu
Administrateur

Re : Erreur lors de l'appel d'une fonction retournant SET OF RECORD

Exact.


Guillaume.

Hors ligne

Pied de page des forums