Thread: plpgsql recursion

plpgsql recursion

From
"Stefano Vita Finzi"
Date:
Greetings!
I have a table like:

node parent  1       2  2       3  3       4

Since i traverse this table with a recursive function, i want to avoid
infinite recursion loop. I have wrote a function to check that a new record
does not create a circular dependency. The function i wrote is as follow:

CREATE OR REPLACE FUNCTION dba_test(INTEGER,INTEGER) RETURNS TEXT AS ' DECLARE   traversing ALIAS FOR $1;   testing
ALIASFOR $2;   t_rec RECORD; BEGIN   FOR t_rec IN SELECT node,parent FROM dba_test WHERE parent = traversing
 
LOOP     IF t_rec.node = testing THEN       RETURN ''Circular'';     ELSE       PERFORM dba_test(t_rec.node,testing);
 END IF;   END LOOP;   RETURN ''ok'' || testing::text; END;
 
' LANGUAGE 'plpgsql';

I would use this function BEFORE inserting the new row. But if i try SELECT
dba_test(4,1); i don't have the result i expect. Can i you give me an hint
where am i wrong?

Thank you!

Stefano Vita Finzi
kluge@despammed.com



Re: plpgsql recursion

From
Rod Taylor
Date:
>       IF t_rec.node = testing THEN
>         RETURN ''Circular'';
>       ELSE
>         PERFORM dba_test(t_rec.node,testing);
>       END IF;
> I would use this function BEFORE inserting the new row. But if i try SELECT
> dba_test(4,1); i don't have the result i expect. Can i you give me an hint
> where am i wrong?

It's probably working as it's written :)  Once it finds 'Curcular' and
returns it to the recursed call of dba_test, you immediately throw away
the return value.

PERFORM should probably be replaced with:

ELSE -- ret is a variable SELECT dba_test(t_rec.node, testing) INTO ret;
 IF ret = ''Circular'' THEN   RETURN ret; END IF;
END IF;


More to the point, if you're attempting to prevent circular items, and
this function will be used in the form of a trigger, then simply RAISE
EXCEPTION.  This way you can ignore having to deal with returned values.


--
Rod Taylor <rbt@rbt.ca>

PGP Key: http://www.rbt.ca/rbtpub.asc

Re: plpgsql recursion

From
Luis Sousa
Date:
Can you post the recursion function that you use on this case to get out 
the information from the table ?

Thanks,
Luis Sousa

Stefano Vita Finzi wrote:

>Greetings!
>I have a table like:
>
>node parent
>   1       2
>   2       3
>   3       4
>
>Since i traverse this table with a recursive function, i want to avoid
>infinite recursion loop. I have wrote a function to check that a new record
>does not create a circular dependency. The function i wrote is as follow:
>
>CREATE OR REPLACE FUNCTION dba_test(INTEGER,INTEGER) RETURNS TEXT AS '
>  DECLARE
>    traversing ALIAS FOR $1;
>    testing ALIAS FOR $2;
>    t_rec RECORD;
>  BEGIN
>    FOR t_rec IN SELECT node,parent FROM dba_test WHERE parent = traversing
>LOOP
>      IF t_rec.node = testing THEN
>        RETURN ''Circular'';
>      ELSE
>        PERFORM dba_test(t_rec.node,testing);
>      END IF;
>    END LOOP;
>    RETURN ''ok'' || testing::text;
>  END;
>' LANGUAGE 'plpgsql';
>
>I would use this function BEFORE inserting the new row. But if i try SELECT
>dba_test(4,1); i don't have the result i expect. Can i you give me an hint
>where am i wrong?
>
>Thank you!
>
>Stefano Vita Finzi
>kluge@despammed.com
>
>
>---------------------------(end of broadcast)---------------------------
>TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>
>
>  
>