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