Thread: PL/pgSQL: dynamic tablename

PL/pgSQL: dynamic tablename

From
Jochem van Dieten
Date:
I am building a set of functions to manage some trees. I would like to
use a dynamic tablename. Something like:

CREATE FUNCTION fn_test(varchar, integer, varchar, varchar) RETURNS
INTEGER AS '
DECLARE
    beforenode INT4;
    newid INT4;
BEGIN
    SELECT INTO beforenode    lft
    FROM    $4
    WHERE    ID = $2;

    More processing

    RETURN newid;
END;
' LANGUAGE 'plpgsql';

Problem is that I always get an error about $4 being used incorrectly.
If I hardcode the name of the table it works just fine.

Does anybody have any suggestion on how to use a dynamic tablename
passed as an attribute in a function?

Jochem


Re: PL/pgSQL: dynamic tablename

From
Tom Lane
Date:
Jochem van Dieten <jochemd@oli.tudelft.nl> writes:
> Does anybody have any suggestion on how to use a dynamic tablename
> passed as an attribute in a function?

You need to use EXECUTE.  See past discussions.

            regards, tom lane

Re: PL/pgSQL: dynamic tablename

From
"Steve Boyle \(Roselink\)"
Date:
Jochem,

You will need to use EXECUTE [sql code] from within your function if your
using dynamic sql.  For reasons why + examples please see:

http://developer.postgresql.org/docs/postgres/plpgsql-statements.html#PLPGSQ
L-STATEMENTS-EXECUTING-DYN-QUERIES

hih

steve boyle


----- Original Message -----
From: "Jochem van Dieten" <jochemd@oli.tudelft.nl>
To: <pgsql-general@postgresql.org>
Sent: Sunday, January 20, 2002 9:08 PM
Subject: [GENERAL] PL/pgSQL: dynamic tablename


> I am building a set of functions to manage some trees. I would like to
> use a dynamic tablename. Something like:
>
> CREATE FUNCTION fn_test(varchar, integer, varchar, varchar) RETURNS
> INTEGER AS '
> DECLARE
> beforenode INT4;
> newid INT4;
> BEGIN
> SELECT INTO beforenode lft
> FROM $4
> WHERE ID = $2;
>
> More processing
>
> RETURN newid;
> END;
> ' LANGUAGE 'plpgsql';
>
> Problem is that I always get an error about $4 being used incorrectly.
> If I hardcode the name of the table it works just fine.
>
> Does anybody have any suggestion on how to use a dynamic tablename
> passed as an attribute in a function?
>
> Jochem
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>


Re: PL/pgSQL: dynamic tablename [resolved]

From
Jochem van Dieten
Date:
Tom Lane wrote:

 > Jochem van Dieten <jochemd@oli.tudelft.nl> writes:
 >
 >> Does anybody have any suggestion on how to use a dynamic tablename
 >> passed as an attribute in a function?
 >>
 >
 > You need to use EXECUTE.  See past discussions.


For the record:
A nested FOR ... IN EXECUTE got me there.

CREATE FUNCTION fn_test(varchar, varchar, integer, varchar) RETURNS
INTEGER AS '
DECLARE
   a_output VARCHAR(4000);
   b_output VARCHAR(4000);
   c_output VARCHAR(4000);
   d_output VARCHAR(4000);
   e_output VARCHAR(4000);
   oldfield VARCHAR(10);
   oldinfo RECORD;
   newinfo RECORD;
BEGIN
   IF $2 = ''ADD'' THEN
     IF $4 = ''sibling'' THEN
       oldfield := ''lft'';
     ELSE
       oldfield := ''rgt'';
     END IF;

     a_output = ''SELECT '' || oldfield || '' AS beforeValue FROM '' ||
$1 || '' WHERE ID = '' || $3;
     FOR oldinfo IN EXECUTE a_output LOOP
       b_output = ''UPDATE '' || $1 || '' SET rgt = rgt + 2 WHERE    rgt >= '' ||
oldinfo.beforeValue;
       c_output = ''UPDATE '' || $1 || '' SET lft = lft + 2 WHERE    lft >= '' ||
oldinfo.beforeValue;
       d_output = ''INSERT INTO '' || $1 || '' (lft, rgt) VALUES ('' ||
oldinfo.beforeValue || '' - 2, '' || oldinfo.beforeValue || '' - 1)'';
       e_output = ''SELECT currval('''''' || $1 || ''_id_seq'''') AS
newid'';
       EXECUTE b_output;
       EXECUTE c_output;
       EXECUTE d_output;
       FOR newinfo IN EXECUTE e_output LOOP
         RETURN newinfo.newid;
       END LOOP;
     END LOOP;
     RETURN 67;
   END IF;
   RETURN 0;
END;
' LANGUAGE 'plpgsql';

Thanks,

Jochem