plpythonu DO support (inline call handler)

Started by Valtonen, Hannuabout 16 years ago3 messages
#1Valtonen, Hannu
hannu.valtonen@hut.fi
2 attachment(s)

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.)

Attachments:

plpython_do_sql.difftext/plain; name=plpython_do_sql.diff; x-mac-creator=0; x-mac-type=0Download
--- 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"

plpython_do.difftext/plain; name=plpython_do.diff; x-mac-creator=0; x-mac-type=0Download
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;
 

#2Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Valtonen, Hannu (#1)
Re: plpythonu DO support (inline call handler)

Valtonen, Hannu wrote:

I couldn't figure out how to get added files to show in git diff ...

git add <new files>
git add -u # to include modified files in the index
git diff --cached

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com

#3Peter Eisentraut
peter_e@gmx.net
In reply to: Valtonen, Hannu (#1)
Re: plpythonu DO support (inline call handler)

On tis, 2009-11-17 at 18:48 +0200, Valtonen, Hannu wrote:

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

committed