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;