Forum OpenACS Q&A: how do you call one pltcl function from another?

Request notifications

I defined a procedure

CREATE FUNCTION meta_class (varchar) RETURNS varchar AS ' ... ' LANGUAGE 'pltcl';

This works fine. But when I want to call it from another tcl procedure I get errors:
bf2=# CREATE FUNCTION foo (varchar) RETURNS varchar AS ' return [meta_class $1] ' LANGUAGE 'pltcl'; bf2'# bf2'# CREATE bf2=# bf2=# select foo(class) from weapon_Types; ERROR: pltcl: invalid command name "meta_class"
This IS possible -- isn't it?
Posted by Jonathan Ellis on
I think this is my problem:

"In Postgres, one and the same function name can be used for different functions as long as the number of arguments or their types differ. This would collide with Tcl procedure names. To offer the same flexibility in PL/Tcl, the internal Tcl procedure names contain the object ID of the procedures pg_proc row as part of their name. Thus, different argtype versions of the same Postgres function are different for Tcl too."

But I still don't know the solution.  I've tried [oid]_[proname], [oid][proname], [proname][oid], [proname]_[oid] and none of these work.

Posted by Jonathan Ellis on
one more try

pltcl.c uses __PLTcl_proc_[oid] (in pltcl_func_handler())

but that doesn't work, either.

Looking at the code it looks like it loads a new tcl interpreter for each function call, and only loads that particular function.  So is there really no way to do this?  Back to PL/PGSQL for me?

The point is that with CREATE FUNCTION you're creating a function in SQL context, and not in Tcl's.

To use your newly created function written in pltcl (or written in any other PG scripting language) from within pltcl you'll have to resort to query execution procs, like spi_exec and friends:

CREATE FUNCTION foo (varchar) RETURNS varchar AS '
   spi_exec "select meta_class(''[quote $1]'') as ret_value"
   return $ret_value
' LANGUAGE 'pltcl';
Note that since meta_class expects varchar you'll need to enclose its argument in single quotes and escape any single quote contained within its argument appropriately.