From 70aa2ae6a5a8fdbba830727104e75efbdf427ed7 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 14 May 2001 22:06:50 +0000 Subject: [PATCH] Remove linking hacks now that dynloader is fixed. --- src/pl/plpython/Makefile | 20 +--- src/pl/plpython/README | 182 +++++---------------------------- src/pl/plpython/dynloader.diff | 12 --- 3 files changed, 26 insertions(+), 188 deletions(-) delete mode 100644 src/pl/plpython/dynloader.diff diff --git a/src/pl/plpython/Makefile b/src/pl/plpython/Makefile index 1ceadc9508..7475cdc1e7 100644 --- a/src/pl/plpython/Makefile +++ b/src/pl/plpython/Makefile @@ -1,4 +1,4 @@ -# $Header: /cvsroot/pgsql/src/pl/plpython/Makefile,v 1.5 2001/05/12 17:49:32 petere Exp $ +# $Header: /cvsroot/pgsql/src/pl/plpython/Makefile,v 1.6 2001/05/14 22:06:50 petere Exp $ subdir = src/pl/plpython top_builddir = ../../.. @@ -12,26 +12,8 @@ SO_MAJOR_VERSION = 0 SO_MINOR_VERSION = 0 OBJS = plpython.o - SHLIB_LINK += $(python_libspec) -# If you have not patched the dynamic loader files as described in the -# README you will have to link these in manually. You may have to add -# more modules. If you have patched the loader, override -# EXTRA_MODULES to be empty. - -# version 2.x -ifneq (,$(findstring 2.,$(python_version))) -EXTRA_MODULES = array cmath errno math md5 operator pcre sha time -endif - -# version 1.x -ifneq (,$(findstring 1.,$(python_version))) -EXTRA_MODULES = arraymodule cmathmodule errnomodule mathmodule md5module operator shamodule timemodule -endif - -SHLIB_LINK += $(addprefix $(python_dynlibdir)/, $(addsuffix $(DLSUFFIX), $(EXTRA_MODULES))) - include $(top_srcdir)/src/Makefile.shlib diff --git a/src/pl/plpython/README b/src/pl/plpython/README index 96a6f06aa5..6a2c68e11c 100644 --- a/src/pl/plpython/README +++ b/src/pl/plpython/README @@ -1,171 +1,39 @@ +PL/Python - Python Procedural Language for PostgreSQL +----------------------------------------------------- +$Id: README,v 1.2 2001/05/14 22:06:50 petere Exp $ -*** INSTALLING *** +Installation: - 0) Build, install or borrow postgresql 7.1, not 7.0. I've got -a language module for 7.0, but it has no SPI interface. Build is best -because it will allow you to do +configure --with-python +cd src/pl/plpython +gmake +gmake install - "cd postgres/src/" - "patch -p2 < dynloader.diff" +Test: -or if that fails open linux.h in src/backend/ports/dynloader and -change the pg_dlopen define from +# have postmaster running... +gmake installcheck -#define pg_dlopen(f) dlopen(f, 2) +Enable language: -to +createlang plpython dbname -#define pg_dlopen(f) dlopen(f, (RTLD_NOW|RTLD_GLOBAL)) -adding the RTLD_GLOBAL flag to the dlopen call allows libpython to -properly resolve symbols when it loads dynamic module. If you can't -patch and rebuild postgres read about DLHACK in the next section. +Note that PL/Python is currently not built automatically because the +code is new and there are some portability issues. - 1) Edit the Makefile. Basically select python 2.0 or 1.5, and set -the include file locations for postgresql and python. If you can't -patch linux.h (or whatever file is appropriate for your architecture) -to add RTLD_GLOBAL to the pg_dlopen/dlopen function and rebuild -postgres. You must uncomment the DLHACK and DLDIR variables. You may -need to alter the DLDIR and add shared modules to DLHACK. This -explicitly links the shared modules to the plpython.so file, and -allows libpython find required symbols. However you will NOT be able -to import any C modules that are not explicitly linked to -plpython.so. Module dependencies get ugly, and all in all it's a -crude hack. +A default Python installation does not provide a shared libpython +library. This is not a problem on many platforms (although it makes +things less efficient), but on some platforms (especially HP-UX) the +link will fail outright. - 2) Run make. +To create a shared libpython, see this web page for hints: - 3) Copy 'plpython.so' to '/usr/local/lib/postgresql/lang/'. -The scripts 'update.sh' and 'plpython_create.sql' are hard coded to -look for it there, if you want to install the module elsewhere edit -them. +http://www.python.org/cgi-bin/faqw.py?req=show&file=faq03.030.htp - 4) Optionally type 'test.sh', this will create a new database -'pltest' and run some checks. (more checks needed) +Place the resulting library in the same directory as the existing +static libpythonX.Y.a and relink plpython. - 5) 'psql -Upostgres yourTESTdb < plpython_create.sql' -*** USING *** - - There are sample functions in 'plpython_function.sql'. -Remember that the python code you write gets transformed into a -function. ie. - -CREATE FUNCTION myfunc(text) RETURNS text - AS -'return args[0]' - LANGUAGE 'plpython'; - -gets tranformed into - -def __plpython_procedure_myfunc_23456(): - return args[0] - -where 23456 is the Oid of the function. - -If you don't provide a return value, python returns the default 'None' -which probably isn't what you want. The language module transforms -python None to postgresql NULL. - -Postgresql function variables are available in the global "args" list. -In the myfunc example, args[0] contains whatever was passed in as the -text argument. For myfunc2(text, int4), args[0] would contain the -text variable and args[1] the int4 variable. The global dictionary SD -is available to store data between function calls. This variable is -private static data. The global dictionary GD is public data, -available to all python functions within a backend. Use with care. -When the function is used in a trigger, the triggers tuples are in -TD["new"] and/or TD["old"] depending on the trigger event. Return -'None' or "OK" from the python function to indicate the tuple is -unmodified, "SKIP" to abort the event, or "MODIFIED" to indicate -you've modified the tuple. If the trigger was called with arguments -they are available in TD["args"][0] to TD["args"][(n -1)] - -Each function gets it's own restricted execution object in the python -interpreter so global data, function arguments from myfunc are not -available to myfunc2. Except for data in the GD dictionary, as -mentioned above. - -The plpython language module automatically imports a python module -called 'plpy'. The functions and constants in this module are -available to you in the python code as 'plpy.foo'. At present 'plpy' -implements the functions 'plpy.error("msg")', 'plpy.fatal("msg")', -'plpy.debug("msg")' and 'plpy.notice("msg")'. They are mostly -equivalent to calling 'elog(LEVEL, "msg")', where level is DEBUG, -ERROR, FATAL or NOTICE. 'plpy.error', and 'plpy.fatal' actually raise -a python exception which if uncaught causes the plpython module to -call elog(ERROR, msg) when the function handler returns from the -python interpreter. Long jumping out of the python interpreter -probably isn't good. 'raise plpy.ERROR("msg")' and 'raise -plpy.FATAL("msg") are equivalent to calling plpy.error or plpy.fatal. - -Additionally the in the plpy module there are two functions called -execute and prepare. Calling plpy.execute with a query string, and -optional limit argument, causing that query to be run, and the result -returned in a result object. The result object emulates a list or -dictionary objects. The result object can be accessed by row number, -and field name. It has these additional methods: nrows() which -returns the number of rows returned by the query, and status which is -the SPI_exec return variable. The result object can be modified. - -rv = plpy.execute("SELECT * FROM my_table", 5) - -returns up to 5 rows from my_table. if my_table a column my_field it -would be accessed as - -foo = rv[i]["my_field"] - -The second function plpy.prepare is called with a query string, and a -list of argument types if you have bind variables in the query. - -plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = -$1", [ "text" ]) - -text is the type of the variable you will be passing as $1. After -preparing you use the function plpy.execute to run it. - -rv = plpy.execute(plan, [ "name" ], 5) - -The limit argument is optional in the call to plpy.execute. - -When you prepare a plan using the plpython module it is automatically -saved. Read the SPI documentation for postgresql for a description of -what this means. Anyway the take home message is if you do: - -plan = plpy.prepare("SOME QUERY") -plan = plpy.prepare("SOME OTHER QUERY") - -You are leaking memory, as I know of no way to free a saved plan. The -alternative of using unsaved plans it even more painful (for me). - -*** BUGS *** - -If the module blows up postgresql or bites your dog, please send a -script that will recreate the behaviour. Back traces from core dumps -are good, but python reference counting bugs and postgresql exeception -handling bugs give uninformative back traces (you can't long_jmp into -functions that have already returned? *boggle*) - -*** TODO *** - -1) create a new restricted execution class that will allow me to pass -function arguments in as locals. passing them as globals means -function cannot be called recursively... - -2) Functions cache the input and output functions for their arguments, -so the following will make postgres unhappy - -create table users (first_name text, last_name text); -create function user_name(user) returns text as 'mycode' language 'plpython'; -select user_name(user) from users; -alter table add column user_id int4; -select user_name(user) from users; - -you have to drop and create the function(s) each time it's arguments -are modified (not nice), don't cache the input and output functions -(slower?), or check if the structure of the argument has been altered -(is this possible, easy, quick?) and recreate cache. - -3) better documentation - -4) suggestions? +Further documentation is available in the PostgreSQL Programmer's +Guide. diff --git a/src/pl/plpython/dynloader.diff b/src/pl/plpython/dynloader.diff deleted file mode 100644 index 718de036c5..0000000000 --- a/src/pl/plpython/dynloader.diff +++ /dev/null @@ -1,12 +0,0 @@ ---- postgresql-snapshot-12-13-2000/src/backend/port/dynloader/linux.h Mon May 29 03:00:17 2000 -+++ postgresql-snapshot/src/backend/port/dynloader/linux.h Sun Feb 4 23:30:59 2001 -@@ -32,7 +32,8 @@ - #endif - #else - /* #define pg_dlopen(f) dlopen(f, 1) */ --#define pg_dlopen(f) dlopen(f, 2) -+/* #define pg_dlopen(f) dlopen(f, 2) */ -+#define pg_dlopen(f) dlopen(f, (RTLD_NOW|RTLD_GLOBAL)) - #define pg_dlsym dlsym - #define pg_dlclose dlclose - #define pg_dlerror dlerror -- 2.40.0