Обсуждение: plperl intial pass
on the patches list, I posted the first files for suuport for using perl as the procedural language. The makefile uses libtool (probably incorrectly). It is not 'safe'. Perl XS modules cannot be used. Using Perl in rules hasn't even been thought about. IF the code looks suspiciously like Jan's code for pltcl - well, it _is_ Jan's code for pltcl horribly mangled. It compiles and runs for me. YMMV. more code and docs to follow. -- Mark Hollomon mhh@mindspring.com
Great,
just compiled and install but need to look at some examples :-)
btw, here is a patch for createlang command to enable plperl
I'm not sure about trusted field.
--- createlang Sat Jul 24 22:27:05 1999
+++ /usr/local/pgsql/bin/createlang Wed Jul 21 19:36:55 1999
@@ -84,9 +84,6 @@ plpgsql) lancomp="PL/pgSQL" trusted="TRUSTED"
handler="plpgsql_call_handler";;
- plperl) lancomp="PL/Perl"
- trusted="TRUSTED"
- handler="plperl_call_handler";; pltcl) lancomp="PL/Tcl"
trusted="TRUSTED" handler="pltcl_call_handler";;
On Fri, 23 Jul 1999, Mark Hollomon wrote:
> Date: Fri, 23 Jul 1999 16:15:10 -0400
> From: Mark Hollomon <mhh@mindspring.com>
> To: pgsql-hackers@postgreSQL.org
> Subject: [HACKERS] plperl intial pass
>
> on the patches list, I posted the first files
> for suuport for using perl as the procedural
> language.
>
> The makefile uses libtool (probably incorrectly).
>
> It is not 'safe'.
>
> Perl XS modules cannot be used.
>
> Using Perl in rules hasn't even been thought about.
>
> IF the code looks suspiciously like Jan's code
> for pltcl - well, it _is_ Jan's code for pltcl
> horribly mangled.
>
> It compiles and runs for me. YMMV.
>
> more code and docs to follow.
> --
> Mark Hollomon
> mhh@mindspring.com
>
_____________________________________________________________
Oleg Bartunov, sci.researcher, hostmaster of AstroNet,
Sternberg Astronomical Institute, Moscow University (Russia)
Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/
phone: +007(095)939-16-83, +007(095)939-23-83
On Sat, Jul 24, 1999 at 10:26:33PM +0400, Oleg Bartunov wrote: > Great, > > just compiled and install but need to look at some examples :-) > btw, here is a patch for createlang command to enable plperl > I'm not sure about trusted field. At this point it definitely should not be trusted. (Trust me). How about the famous hello world: create function hello () returns text as ' return "Hello world!";' language 'plperl'; or a quick sum: create function sum2 (int4, int4) returns int4 as ' $_[0] + $_[1];' language 'plperl'; The args are in @_ (naturally). Tuples are passed as hash references. Access to SPI functionality is coming. -- Mark Hollomon mhh@mindspring.com
Great ! at least your examples works: test=> select hello(); NOTICE: plperl_func_handler: have been asked to call __PLperl_proc_329289 NOTICE: plperl_func_handler: __PLperl_proc_329289 was in the hash NOTICE: plperl_call_perl_func: calling __PLperl_proc_329289 NOTICE: plperl_func_handler: returned from plperl_call_perl_func NOTICE: plperl_func_handler: return as string = Hello world! NOTICE: plperl_func_handler: Datum is 826ee30 hello ------------ Hello world! (1 row) test=> create function sum2 (int4, int4) returns int4 as ' test'> $_[0] + $_[1];' language 'plperl'; CREATE test=> select sum2(4,2); NOTICE: plperl_func_handler: have been asked to call __PLperl_proc_329290 NOTICE: plperl_func_handler: __PLperl_proc_329290 doesn't exist yet NOTICE: plperl_create_sub: creating the sub NOTICE: plperl_call_perl_func: calling __PLperl_proc_329290 NOTICE: plperl_func_handler: returned from plperl_call_perl_func NOTICE: plperl_func_handler: return as string = 6 NOTICE: plperl_func_handler: Datum is 6 sum2 ---- 6 (1 row) Regards, Oleg On Sun, 25 Jul 1999, Mark Hollomon wrote: > Date: Sun, 25 Jul 1999 12:08:51 -0400 > From: Mark Hollomon <mhh@mindspring.com> > To: Oleg Bartunov <oleg@sai.msu.su> > Cc: pgsql-hackers@postgreSQL.org > Subject: Re: [HACKERS] plperl intial pass > > On Sat, Jul 24, 1999 at 10:26:33PM +0400, Oleg Bartunov wrote: > > Great, > > > > just compiled and install but need to look at some examples :-) > > btw, here is a patch for createlang command to enable plperl > > I'm not sure about trusted field. > > At this point it definitely should not be trusted. (Trust me). > > How about the famous hello world: > > create function hello () returns text as ' > return "Hello world!";' language 'plperl'; > > or a quick sum: > > create function sum2 (int4, int4) returns int4 as ' > $_[0] + $_[1];' language 'plperl'; > > The args are in @_ (naturally). Tuples are passed as > hash references. > > Access to SPI functionality is coming. > > > > -- > Mark Hollomon > mhh@mindspring.com > _____________________________________________________________ Oleg Bartunov, sci.researcher, hostmaster of AstroNet, Sternberg Astronomical Institute, Moscow University (Russia) Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/ phone: +007(095)939-16-83, +007(095)939-23-83
On 24-Jul-99 Oleg Bartunov wrote: > Great, > > just compiled and install but need to look at some examples :-) > btw, here is a patch for createlang command to enable plperl > I'm not sure about trusted field. Does plperl use Perl interpreter or it's completly different language with similar syntax? Do you have some speed/memory statistic or plpgsql/plperl comparison ? --- Dmitry Samersoff, dms@wplus.net, ICQ:3161705 http://devnull.wplus.net * There will come soft rains ...
>
> Great,
>
> just compiled and install but need to look at some examples :-)
> btw, here is a patch for createlang command to enable plperl
> I'm not sure about trusted field.
>
> --- createlang Sat Jul 24 22:27:05 1999
> +++ /usr/local/pgsql/bin/createlang Wed Jul 21 19:36:55 1999
> @@ -84,9 +84,6 @@
> plpgsql) lancomp="PL/pgSQL"
> trusted="TRUSTED"
> handler="plpgsql_call_handler";;
> - plperl) lancomp="PL/Perl"
> - trusted="TRUSTED"
> - handler="plperl_call_handler";;
> pltcl) lancomp="PL/Tcl"
> trusted="TRUSTED"
> handler="pltcl_call_handler";;
I wouldn't make it a TRUSTED language right now, because
until PL/Perl has a safe mode (what Mark said it hasn't now)
it is a security hole. Unpriviliged users could create
functions in PL/Perl that modify the hba.conf!
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Dmitry Samersoff wrote:
>
> On 24-Jul-99 Oleg Bartunov wrote:
> > Great,
> >
> > just compiled and install but need to look at some examples :-)
> > btw, here is a patch for createlang command to enable plperl
> > I'm not sure about trusted field.
>
> Does plperl use Perl interpreter or it's completly different language
> with similar syntax?
>
> Do you have some speed/memory statistic or plpgsql/plperl comparison ?
It uses a real Perl precompiler/interpreter inside.
I think it's far too early for such comparisions. As Mark
wrote, PL/Perl's SPI interface (for accessing tables from
inside a function) is still to come, and if I remember right,
triggers are another delayed feature up to now.
When it's done, I would expect that PL/Perl could outperform
PL/pgSQL in many cases. I haven't done speed comparision
between PL/pgSQL and PL/Tcl yet, but I know all their
internals. The reason for my assumtion is that PL/pgSQL uses
the PostgreSQL executor for all computations. That's IMHO a
pro, because it assures that any defined datatype, function,
operator and aggregate is automagically available in PL/pgSQL
and all computations return exactly the same result as if
they're done inside an SQL statement. But nothing on earth is
for free, not even the death - you pay for it with your life.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Mark Hollomon wrote:
>
> on the patches list, I posted the first files
> for suuport for using perl as the procedural
> language.
Congratulations!
>
> The makefile uses libtool (probably incorrectly).
>
> It is not 'safe'.
>
> Perl XS modules cannot be used.
What's an XS module? If it's a shared object dynamically
linked - don't care too much - PL/Tcl cannot either.
>
> Using Perl in rules hasn't even been thought about.
If a function works from a query, the same function must work
too in a rule because the rewriter only mangles up parsetrees
so when executing, they are invoked from a query. Or did you
mean triggers?
>
> IF the code looks suspiciously like Jan's code
> for pltcl - well, it _is_ Jan's code for pltcl
> horribly mangled.
What ya think where the skeleton for PL/pgSQL came from :-) I
just wrote my own SQL scripting bytecode compiler and
executor and placed them into the PL/Tcl sources.
Congrats again - great work - move on.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Dmitry Samersoff wrote: > > On 24-Jul-99 Oleg Bartunov wrote: > > Great, > > > > just compiled and install but need to look at some examples :-) > > btw, here is a patch for createlang command to enable plperl > > I'm not sure about trusted field. > > Does plperl use Perl interpreter or it's completly different language > with similar syntax? > It imbeds the perl interpreter. Just as pltcl imbeds the tcl interpreter. > Do you have some speed/memory statistic or plpgsql/plperl comparison ? No. -- Mark Hollomon mhh@nortelnetworks.com ESN 451-9008 (302)454-9008
Jan Wieck wrote: > > Mark Hollomon wrote: > > > > > It is not 'safe'. > > > > Perl XS modules cannot be used. > > What's an XS module? If it's a shared object dynamically > linked - don't care too much - PL/Tcl cannot either. Correct. The problem is that the Opcode module, which allows you to disable features of the compiler (to close security holes) is an XS module. In theory, it is possible to do without Opcode, but doing so would create a very heavy perl version dependency in plperl. So, I have to get XS stuff working in order to disallow XS stuff. sigh. And plperl can never be trusted until I can forbid writing to the filesystem. > > > > > Using Perl in rules hasn't even been thought about. > > If a function works from a query, the same function must work > too in a rule because the rewriter only mangles up parsetrees > so when executing, they are invoked from a query. Or did you > mean triggers? Ick. Correct. I meant triggers. -- Mark Hollomon mhh@nortelnetworks.com ESN 451-9008 (302)454-9008
Mark Hollomon wrote:
>
> Jan Wieck wrote:
> >
>
> Correct. The problem is that the Opcode module, which allows you to
> disable features of the compiler (to close security holes) is an
> XS module. In theory, it is possible to do without Opcode, but
> doing so would create a very heavy perl version dependency in plperl.
>
> So, I have to get XS stuff working in order to disallow XS stuff.
> sigh.
>
> And plperl can never be trusted until I can forbid writing to the
> filesystem.
I see. Maybe it's possible to get the Opcode stuff working
without full XS? Adding full XS support only to disable it -
what an overkill :-)
Correct me if I'm wrong (I'm only guessing). Like for Perl,
the Tcl interpreter itself sits in a library. To create the
standalone tclsh, a small tclAppInit.c file is compiled into
the tclsh executable. The default one only creates one
interpreter and arranges for the execution of the script
given in argv[0] or starts up the interactive shell.
A dynamically loadable Tcl module contains one special
function named <libname>_Init() where first character of
libname is capitalized. On dynamic load, this function is
called with the invoking interpreter as argument. This
function then calls Tcl_CreateCommand() etc. to tell Tcl
what's coming here and does other module specific
initializations.
It is now possible, to add other stuff to tclAppInit.c (like
calls to Mymodule_Init) and link it against some more than
libtcl.so. That was the standard solution before dynamic
loading was that easy as it is today (back in the days of
a.out libs).
Your plperl.c is mostly my pltcl.c - so I assume it does the
same things mainly. Create an interpreter and throw some
strings into it, hoping they are intelligable in some way (at
least produce a helpful error message). Thus, it might be
possible to add calls to the initializations for the Opcode
XS directly into the plperl module after creating the
interpreter and link it against Opcode as well.
This is just the way I would do it for Tcl and I'll surely do
it someday. I would like to have a second, unsafe
interpreter in the module. That could then modify files or
use the frontend library to access a different database on
another server. Needless to say that this then would be an
untrusted language, available only for db superusers.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Jan Wieck wrote:
>
> Mark Hollomon wrote:
> >
> > Jan Wieck wrote:
> > >
> >
> > Correct. The problem is that the Opcode module, which allows you to
> > disable features of the compiler (to close security holes) is an
> > XS module. In theory, it is possible to do without Opcode, but
> > doing so would create a very heavy perl version dependency in plperl.
> >
> > So, I have to get XS stuff working in order to disallow XS stuff.
> > sigh.
> >
> > And plperl can never be trusted until I can forbid writing to the
> > filesystem.
>
> I see. Maybe it's possible to get the Opcode stuff working
> without full XS? Adding full XS support only to disable it -
> what an overkill :-)
>
> Correct me if I'm wrong (I'm only guessing). Like for Perl,
> the Tcl interpreter itself sits in a library. To create the
> standalone tclsh, a small tclAppInit.c file is compiled into
> the tclsh executable. The default one only creates one
> interpreter and arranges for the execution of the script
> given in argv[0] or starts up the interactive shell.
>
> A dynamically loadable Tcl module contains one special
> function named <libname>_Init() where first character of
> libname is capitalized. On dynamic load, this function is
> called with the invoking interpreter as argument. This
> function then calls Tcl_CreateCommand() etc. to tell Tcl ^^^^^^^^^^^^^^^^^
And here-in lies the problem. Tcl_CreateCommand is sitting, not
in the executable, but in the shared-lib with the function call
handler. dlopen(), by default will not link across shared-libs.
postgres /-----/ \-----\ | | plperl.so ---> Opcode.so ^^
This link doesn't happen.
Passing RTLD_GLOBAL (I think) as a flag to dlopen makes the symbols
in a shared-lib available for linking into the next shared-lib.
But postgresql doesn't use the RTLD_GLOBAL flag and patching the
backend to load _everything_ with RTLD_GLOBAL seemed like it could
have less than desirable behavior.
a.out systems are easier since perl's dynamic loading subsystem
would take care of problem for me.
> what's coming here and does other module specific
> initializations.
>
> It is now possible, to add other stuff to tclAppInit.c (like
> calls to Mymodule_Init) and link it against some more than
> libtcl.so. That was the standard solution before dynamic
> loading was that easy as it is today (back in the days of
> a.out libs).
That is exactly how it works. But see above.
And on top of the above problem, postgres assumes all linuxen
use a.out type loading. Where as perl uses dlopen where it can.
Getting those two to play together is more than I care to attempt.
I am researching a fix now to let linux installations use dlopen
if it is available.
I would not be unhappy if somebody beats me to it.
> This is just the way I would do it for Tcl and I'll surely do
> it someday. I would like to have a second, unsafe
> interpreter in the module. That could then modify files or
> use the frontend library to access a different database on
> another server. Needless to say that this then would be an
> untrusted language, available only for db superusers.
>
Yes, I've been thinking about that as well. It would be nice to have
permissions based on userid. Maybe the 'suid' stuff that is being
discussed in another thread will gives us a mechanism.
--
Mark Hollomon
mhh@nortelnetworks.com
ESN 451-9008 (302)454-9008
Mark Hollomon wrote:
> > A dynamically loadable Tcl module contains one special
> > function named <libname>_Init() where first character of
> > libname is capitalized. On dynamic load, this function is
> > called with the invoking interpreter as argument. This
> > function then calls Tcl_CreateCommand() etc. to tell Tcl
> ^^^^^^^^^^^^^^^^^
>
> And here-in lies the problem. Tcl_CreateCommand is sitting, not
> in the executable, but in the shared-lib with the function call
> handler. dlopen(), by default will not link across shared-libs.
>
> postgres
> /-----/ \-----\
> | |
> plperl.so ---> Opcode.so
> ^^
> This link doesn't happen.
But it does for PL/Tcl - at least under Linux-ELF. (C = Call
to, L = Location of functions code segment):
+-------------------------+
| postgres |
+-------------------------+
|
| dynamic load
|
v
+---------------------------+ +---------------------------+
| pltcl.so |--------->| libtcl8.0.so |
| | auto- | |
| C Tcl_CreateInterp() | dynamic | L Tcl_CreateInterp() |
| C Tcl_CreateCommand() | load | L Tcl_CreateCommand() |
| L static pltcl_SPI_exec() | | C pltcl_SPI_exec() |
+---------------------------+ +---------------------------+
After loading of pltcl.so, it calls Tcl_CreateInterp() to
build a Tcl interpreter, and then calls Tcl_CreateCommand()
to tell that interpreter the address of one of it's hidden
(static) functions plus a name for it from the script side.
The interpreter just remembers this in it's command hash
table, and if that keyword occurs when it expects a
command/procedure name, just calls it via the function
pointer.
There is no -ltcl8.0 switch in the link step of postgres.
The fact that pltcl.so needs something out of libtcl8.0.so is
told when linking pltcl.so:
gcc -shared -o pltcl.so pltcl.o -L/usr/local/lib -ltcl8.0
That results in this:
[pgsql@hot] ~ > ldd bin/postgres
libdl.so.1 => /lib/libdl.so.1 (0x4000a000)
libm.so.5 => /lib/libm.so.5 (0x4000d000)
libtermcap.so.2 => /usr/lib/libtermcap.so.2 (0x40016000)
libncurses.so.3.0 => /lib/libncurses.so.3.0 (0x4001a000)
libc.so.5 => /lib/libc.so.5 (0x4005b000)
[pgsql@hot] ~ > ldd lib/pltcl.so
./lib/pltcl.so => ./lib/pltcl.so (0x4000a000)
libc.so.5 => /lib/libc.so.5 (0x40010000)
libtcl8.0.so => /usr/local/lib/libtcl8.0.so (0x400cb000)
As you see, there is no libtcl mentioned in the shared lib
dependencies of the postgres backend. It's the pltcl.so
shared object that remembers this. And if you invoke "ldd -r
-d pltcl.so" it will print alot of unresolveable symbols, but
most of them are backend symbols (the others are math ones
because the above gcc -shared call is in fact incomplete -
but since the backend is already linked against libm.so it
doesn't matter :-).
So if I want to use My dynamically loadable package for Tcl
from inside the PL/Tcl interpreter, I would have to call
My_Init() from pltcl.so AND add My.so to the linkage of
pltcl.so. Calling My_Init() causes that "pltcl.o" has an
unresolved reference to symbol _My_Init. The linker find's it
in My.so and saves this info in pltcl.so so the dynamic
loader can (and does) resolve it whenever something load
pltcl.so.
The important key is to reference at least one symbol in the
shared lib you want to get automatically loaded. You can add
as much link libs with -l as you want. If none of their
symbols is needed, the linker will not save this dependency
(because there is none) in the resulting .so.
I'll give it a try and USE some binary Tcl packages from
inside. Will tell ya soon.
> Getting those two to play together is more than I care to attempt.
> I am researching a fix now to let linux installations use dlopen
> if it is available.
Don't think you need to.
> > This is just the way I would do it for Tcl and I'll surely do
> > it someday. I would like to have a second, unsafe
> > interpreter in the module. That could then modify files or
> > use the frontend library to access a different database on
> > another server. Needless to say that this then would be an
> > untrusted language, available only for db superusers.
> >
>
> Yes, I've been thinking about that as well. It would be nice to have
> permissions based on userid. Maybe the 'suid' stuff that is being
> discussed in another thread will gives us a mechanism.
I know, I know - and I know how. It cannot work for
"internal" language functions. But for anything that goes
through some loading (dynloader or PL call hander), the fmgr
looks up pg_proc and put's informations into the FmgrInfo
struct. Adding a setuid field to pg_proc and remembering that
too wouldn't be too much and it then would know when calling
such a beast. Fmgr then manages a current user stack which
must be reset on a transaction abort. Anything that needs the
current user simply looks at the toplevel stack entry.
This is totally transparent then for all non-builtin
functions and all non-builtin triggers (where I don't know of
one).
Maybe I kept this far too long in mind. But I thought about
some more complicated changes to the function call interface
for a while that would require touching several dozens of
source files (single argument NULL identification, returning
tuples and tuple SET's). Doing SETUID would have been some
DONE WHILE AT IT. I really should do it earlier than the
SET's, because they require subselecting RTE's (which it the
third thread now - eh - I better shut up).
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Jan Wieck wrote: > > Mark Hollomon wrote: > > > Yes, I've been thinking about that as well. It would be nice to have > > permissions based on userid. Maybe the 'suid' stuff that is being > > discussed in another thread will gives us a mechanism. > > I know, I know - and I know how. It cannot work for > "internal" language functions. But for anything that goes > through some loading (dynloader or PL call hander), the fmgr > looks up pg_proc and put's informations into the FmgrInfo > struct. Adding a setuid field to pg_proc and remembering that > too wouldn't be too much and it then would know when calling > such a beast. Fmgr then manages a current user stack which > must be reset on a transaction abort. Anything that needs the > current user simply looks at the toplevel stack entry. That would work. > > This is totally transparent then for all non-builtin > functions and all non-builtin triggers (where I don't know of > one). > > Maybe I kept this far too long in mind. But I thought about > some more complicated changes to the function call interface > for a while that would require touching several dozens of > source files (single argument NULL identification, returning > tuples and tuple SET's). Doing SETUID would have been some > DONE WHILE AT IT. I really should do it earlier than the > SET's, because they require subselecting RTE's (which it the > third thread now - eh - I better shut up). I've been looking at returning a tuple. It looked to me that the executor would handle a returned tuple okay, it was just SETs that would cause problems. But I suspect I am wrong. The best I could come up with for creating the tuple was using heap_formtuple. But that requires a TupleDesc so I was going to use heap_openr. But that needs the name of the relation which is avaible from the Form_pg_data (?) structure for the return type, which we already must get. -- Mark Hollomon mhh@nortelnetworks.com ESN 451-9008 (302)454-9008
Jan Wieck wrote:
>
> Mark Hollomon wrote:
>
> > Jan Wieck wrote:
> > >
> > > A dynamically loadable Tcl module contains one special
> > > function named <libname>_Init() where first character of
> > > libname is capitalized. On dynamic load, this function is
> > > called with the invoking interpreter as argument. This
> > > function then calls Tcl_CreateCommand() etc. to tell Tcl
> > ^^^^^^^^^^^^^^^^^
> >
> > And here-in lies the problem. Tcl_CreateCommand is sitting, not
> > in the executable, but in the shared-lib with the function call
> > handler. dlopen(), by default will not link across shared-libs.
> >
> > postgres
> > /-----/ \-----\
> > | |
> > plperl.so ---> Opcode.so
> > ^^
> > This link doesn't happen.
>
> But it does for PL/Tcl - at least under Linux-ELF. (C = Call
> to, L = Location of functions code segment):
>
> +-------------------------+
> | postgres |
> +-------------------------+
> |
> | dynamic load
> |
> v
> +---------------------------+ +---------------------------+
> | pltcl.so |--------->| libtcl8.0.so |
> | | auto- | |
> | C Tcl_CreateInterp() | dynamic | L Tcl_CreateInterp() |
> | C Tcl_CreateCommand() | load | L Tcl_CreateCommand() |
> | L static pltcl_SPI_exec() | | C pltcl_SPI_exec() |
> +---------------------------+ +---------------------------+
>
> After loading of pltcl.so, it calls Tcl_CreateInterp() to
> build a Tcl interpreter, and then calls Tcl_CreateCommand()
> to tell that interpreter the address of one of it's hidden
> (static) functions plus a name for it from the script side.
> The interpreter just remembers this in it's command hash
> table, and if that keyword occurs when it expects a
> command/procedure name, just calls it via the function
> pointer.
AHHH, now I understand the difference. By default, the perl installation
does not create a shared library. It creates a static archive only.
And the three linux distros that I have experience with don't force
the creation of the shared lib. So, my situation is:
postgres | | +----------------------+ +-----------------+ | plperl.so |
| Opcode.so | | +--------------+ | | | | | libperl.a | <-+------------|
| | +--------------+ | | | +----------------------+
+-----------------+
And it is THAT link that I cannot get to happen without the RTLD_GLOBAL
flag I mentioned.
Sorry for the confusion.
Hopefully you can help find a way out of this.
I had a patch to change the way dynloader worked on linuxelf,
but over night my disk crashed. brand new UDMA/66 drive. Grrrr.
--
Mark Hollomon
mhh@nortelnetworks.com
ESN 451-9008 (302)454-9008
Mark Hollomon wrote:
> I've been looking at returning a tuple. It looked to me that the
>
> executor would handle a returned tuple okay, it was just SETs that
> would cause problems. But I suspect I am wrong.
Functions returning SET's allways return SET's of tuples,
never SET's of single values. And functions returning tuple
(SET's) have a targetlist to specify which attribute of the
returned tuple(s) is wanted. It is the processing of this
funciton-call-targetlist that's actually broken in the
executor.
But it's not worth fixing it without beeing able after to use
more than one attribute of the returned set. And that
requires the mentioned subselecting RTE. So you could then
say things like:
SELECT X.a, X.c FROM mysetfunc('Mark') X;
The next problem in returning SET's is, that PostgreSQL isn't
a state machine - it is stack oriented. The way it was
supposed to work with SQL language functions was this:
1. The last query in an SQL function returning a tuple SET
is allways a SELECT.
2. When the FUNC node is first hit during execution, the
function is called. Then the FUNC node is modified by
the executor and references the execution tree of the
last command in the function.
3. Subsequent function calls don't invoke the function
again, instead functions last commands execution tree is
asked for the next tuple.
This mechanism could also work for PL functions. A PL
function returning a SET creates a temp table. At each
occurence of
RETURN mytup AND RESUME;
it adds the tuple to the temp table. If it finally really
returns, it hands back an execution plan for a
SELECT * FROM <my_invocations_temp_table>;
Then again, the problem of using multiple attributes of the
returned set remains.
> The best I could come up with for creating the tuple was using
>
> heap_formtuple. But that requires a TupleDesc so I was going to
>
> use heap_openr. But that needs the name of the relation which is
>
> avaible from the Form_pg_data (?) structure for the return type,
>
> which we already must get.
Of course, the PL function must create tuples via
heap_formtuple(). Thus, we need a pg_class entry (etc.) for
it. The PL handler knows the return type of the function it's
handling from pg_proc. The corresponding pg_type entry has a
non-zero typrelid indicating that it's a tuple type. Simply
use heap_open() with that typrelid and you'll get it.
I'd like to add a new type of relation when we go for return
SET's.
CREATE STRUCTURE structname (attname type [, ...]);
It just causes another pg_class entry, but these relations
aren't accessible by normal means and do not have an
underlying file. Don't know if it's valid SQL syntax, but
what else could tell the parser what type of a tuple a SET
function will return if it's not an existing relation
structure?
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Mark Hollomon wrote:
> AHHH, now I understand the difference. By default, the perl installation
> does not create a shared library. It creates a static archive only.
> And the three linux distros that I have experience with don't force
> the creation of the shared lib. So, my situation is:
>
> postgres
> |
> |
> +----------------------+ +-----------------+
> | plperl.so | | Opcode.so |
> | +--------------+ | | |
> | | libperl.a | <-+------------| |
> | +--------------+ | | |
> +----------------------+ +-----------------+
>
> And it is THAT link that I cannot get to happen without the RTLD_GLOBAL
> flag I mentioned.
Yes - we need to understand the differences. After looking at
some perl manpages (perlxs, perlembed, perlmodlib etc.) and
consulting Opcode.pm I see the problems clearer now.
Under Tcl, you can simply type "load <shared-object>" to load
a .so and cause a call to it's ..._Init() function. Whatever
comes there, the .so's ..._Init() function will tell it. And
since every C function that should be callable from Tcl is
given to the interpreter as a function pointer from within
the ..._Init(), nothing except the ..._Init() function itself
must be really resolved. In fact, the functions called from
Tcl can be declared static inside the shared object (what's
true in pltcl) so there are no symbols to resolve.
A safe Tcl interpreter has no load command. But the
controlling C application can call the .so's ..._Init()
function directly to simulate the "load" (well, it should be
the ..._SafeInit(), but that's another story). Thus, a C
application creating a safe interpreter can load modules for
it even if the interpreter itself can't.
Under Perl, a package using a shared object is allways
surrounded by some .pm which tells to lookup symbols via the
dynamic loader (if I understand XSUB's right). So it's still
a type of a script that controls the Perl->C-function
bindings, not the shared object itself.
The detail I don't understand is what breaks Perl's
dynaloader if you use it from inside of plperl.so. Since Perl
isn't built shared, the entire libperl.a should be linked
static into plperl.so. What's the exact error message when
you try to USE Opcode?
>
> Sorry for the confusion.
>
> Hopefully you can help find a way out of this.
>
> I had a patch to change the way dynloader worked on linuxelf,
I don't think you should change the entire dynamic loader of
PostgreSQL for it. This could be a can of worms and you
should be happy that these problems showed up already on your
development platform. I don't expect that you're willing to
fix the dynamic loading under AIX, HP-UX and Solaris too
(maybe you can't because the lack of appropriate
environment).
> but over night my disk crashed. brand new UDMA/66 drive. Grrrr.
Ech
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#========================================= wieck@debis.com (Jan Wieck) #
Jan Wieck wrote: > > Mark Hollomon wrote: > > > I had a patch to change the way dynloader worked on linuxelf, > > I don't think you should change the entire dynamic loader of > PostgreSQL for it. This could be a can of worms and you > should be happy that these problems showed up already on your > development platform. I don't expect that you're willing to > fix the dynamic loading under AIX, HP-UX and Solaris too > (maybe you can't because the lack of appropriate > environment). > The problem is that perl and postgres disagree as how to do the dynamic loading. postgres (on linux) _Always_ use aout style dynamic loading. Perl checks to see if the system is ELF and use dlopen if it is. On my ELF system then, postgres is loading plperl.so with dl_open (?). Then perl is loading Opcode.so using dlopen. The problem seems to be that the symbols from libperl.a (in plperl.so) are not available for resolving missing symbols in Opcode.so. The error message basically mentions every perl symbol as 'unresolved'. I noticed in another thread that D'Arcy is strugling with a similar problem in NetBSD. On my system, once I got postgres and perl to agree on how to do dynamic loading, I got XS stuff working. The code is (mostly) already in plperl.c, but ifdef'ed out. -- Mark Hollomon mhh@nortelnetworks.com ESN 451-9008 (302)454-9008