Hi,

The attached patch adds support for DO clause in plpythonu. It was heavily inspired by the plperl and plpgsql inline handler code.

I couldn't figure out how to get added files to show in git diff so the two files that this patch adds: expected/plpython_do.out and expected/plpython_do.sql are added as diff -uN 's in plpython_do_sql.diff

- Hannu

ps.
(This is a resend of the patch since I sent it a couple of days ago and the original message seems to have been lost to the moderation queue so now I subscribed.)
--- jee 1970-01-01 02:00:00.000000000 +0200
+++ sql/plpython_do.sql 2009-11-16 09:11:07.000000000 +0200
@@ -0,0 +1 @@
+DO $$ plpy.notice("This is plpythonu") $$ LANGUAGE plpythonu;
--- jee 1970-01-01 02:00:00.000000000 +0200
+++ expected/plpython_do.out    2009-11-16 09:11:31.000000000 +0200
@@ -0,0 +1,3 @@
+DO $$ plpy.notice("This is plpythonu") $$ LANGUAGE plpythonu;
+NOTICE:  This is plpythonu
+CONTEXT:  PL/Python function "inline_plpythonu_function"

diff --git a/src/include/catalog/pg_pltemplate.h 
b/src/include/catalog/pg_pltemplate.h
index 5ef97df..6eb6235 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -72,6 +72,6 @@ DATA(insert ( "pltcl"         t t "pltcl_call_handler" _null_ 
_null_ "$libdir/pltcl" _n
 DATA(insert ( "pltclu"         f f "pltclu_call_handler" _null_ _null_ 
"$libdir/pltcl" _null_ ));
 DATA(insert ( "plperl"         t t "plperl_call_handler" _null_ 
"plperl_validator" "$libdir/plperl" _null_ ));
 DATA(insert ( "plperlu"                f f "plperl_call_handler" _null_ 
"plperl_validator" "$libdir/plperl" _null_ ));
-DATA(insert ( "plpythonu"      f f "plpython_call_handler" _null_ _null_ 
"$libdir/plpython" _null_ ));
+DATA(insert ( "plpythonu"      f f "plpython_call_handler" 
"plpython_inline_handler" _null_ "$libdir/plpython" _null_ ));
 
 #endif   /* PG_PLTEMPLATE_H */
diff --git a/src/pl/plpython/Makefile b/src/pl/plpython/Makefile
index 373bc79..9cae5f2 100644
--- a/src/pl/plpython/Makefile
+++ b/src/pl/plpython/Makefile
@@ -60,6 +60,7 @@ REGRESS_OPTS = --dbname=$(PL_TESTDB) --load-language=plpythonu
 REGRESS = \
        plpython_schema \
        plpython_populate \
+        plpython_do \
        plpython_test \
        plpython_global \
        plpython_import \
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 6fd4aca..ced874d 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -195,14 +195,16 @@ typedef struct PLyResultObject
 
 /* function declarations */
 
-/* Two exported functions: first is the magic telling Postgresql
- * what function call interface it implements. Second is for
- * initialization of the interpreter during library load.
+/* Three exported functions: first is the magic telling Postgresql
+ * the function call interface it implements. Second one is for the inline 
call handler
+ * and the third one is for initialization of the interpreter during library 
load.
  */
 Datum          plpython_call_handler(PG_FUNCTION_ARGS);
+Datum          plpython_inline_handler(PG_FUNCTION_ARGS);
 void           _PG_init(void);
 
 PG_FUNCTION_INFO_V1(plpython_call_handler);
+PG_FUNCTION_INFO_V1(plpython_inline_handler);
 
 /* most of the remaining of the declarations, all static */
 
@@ -378,6 +380,65 @@ plpython_return_error_callback(void *arg)
 }
 
 Datum
+plpython_inline_handler(PG_FUNCTION_ARGS)
+{
+        InlineCodeBlock *codeblock = (InlineCodeBlock *) 
DatumGetPointer(PG_GETARG_DATUM(0));
+        Datum retval;
+       FunctionCallInfoData fake_fcinfo;
+       FmgrInfo flinfo;
+
+       PLyProcedure *save_curr_proc;
+       PLyProcedure *volatile proc = NULL;
+       ErrorContextCallback plerrcontext;
+
+       if (SPI_connect() != SPI_OK_CONNECT)
+           elog(ERROR, "SPI_connect failed");
+
+       MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+       MemSet(&flinfo, 0, sizeof(flinfo));
+       fake_fcinfo.flinfo = &flinfo;                                           
                                 
+       flinfo.fn_oid = InvalidOid;                                             
                                 
+       flinfo.fn_mcxt = CurrentMemoryContext; 
+
+       save_curr_proc = PLy_curr_procedure;
+       plerrcontext.callback = plpython_error_callback;
+       plerrcontext.arg = codeblock->source_text;
+       plerrcontext.previous = error_context_stack;
+       error_context_stack = &plerrcontext;
+
+       proc = PLy_malloc(sizeof(PLyProcedure));
+       proc->proname = PLy_strdup("inline_plpythonu_function");
+       proc->pyname = PLy_strdup("inline_plpythonu _function");
+       proc->result.is_rowtype = 1;
+       proc->me = PyCObject_FromVoidPtr(proc, NULL);
+
+       PG_TRY();
+       {
+                       PLy_procedure_compile(proc, codeblock->source_text);
+                       PLy_curr_procedure = proc;
+                       retval = PLy_function_handler(&fake_fcinfo, proc);
+       }
+       PG_CATCH();
+       {
+               PLy_curr_procedure = save_curr_proc;
+               if (proc)
+               {
+                       /* note: Py_DECREF needs braces around it, as of 
2003/08 */
+                       Py_DECREF(proc->me);
+               }
+               PyErr_Clear();
+               PG_RE_THROW();
+       }
+       PG_END_TRY();
+       /* Pop the error context stack */
+       error_context_stack = plerrcontext.previous;
+
+       PLy_curr_procedure = save_curr_proc;
+       Py_DECREF(proc->me);
+       return retval;
+}
+
+Datum
 plpython_call_handler(PG_FUNCTION_ARGS)
 {
        Datum           retval;
@@ -391,11 +452,11 @@ plpython_call_handler(PG_FUNCTION_ARGS)
        save_curr_proc = PLy_curr_procedure;
 
        /*
-     * Setup error traceback support for ereport()
-     */
-    plerrcontext.callback = plpython_error_callback;
-    plerrcontext.previous = error_context_stack;
-    error_context_stack = &plerrcontext;
+        * Setup error traceback support for ereport()
+        */
+       plerrcontext.callback = plpython_error_callback;
+       plerrcontext.previous = error_context_stack;
+       error_context_stack = &plerrcontext;
 
        PG_TRY();
        {
@@ -431,7 +492,7 @@ plpython_call_handler(PG_FUNCTION_ARGS)
        PG_END_TRY();
 
        /* Pop the error context stack */
-    error_context_stack = plerrcontext.previous;
+       error_context_stack = plerrcontext.previous;
 
        PLy_curr_procedure = save_curr_proc;
 

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to