Skip to content

Commit adb7764

Browse files
committed
PL/Python DO handler
Also cleaned up some redundancies between the primary error messages and the error context in PL/Python. Hannu Valtonen
1 parent 306a428 commit adb7764

File tree

8 files changed

+102
-16
lines changed

8 files changed

+102
-16
lines changed

doc/src/sgml/plpython.sgml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.43 2009/12/19 22:23:21 petere Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.44 2010/01/22 15:45:15 petere Exp $ -->
22

33
<chapter id="plpython">
44
<title>PL/Python - Python Procedural Language</title>
@@ -551,6 +551,24 @@ $$ LANGUAGE plpythonu;
551551
</para>
552552
</sect1>
553553

554+
<sect1 id="plpython-do">
555+
<title>Anonymous Code Blocks</title>
556+
557+
<para>
558+
PL/Python also supports anonymous code blocks called with the
559+
<xref linkend="sql-do"> statement:
560+
561+
<programlisting>
562+
DO $$
563+
# PL/Python code
564+
$$ LANGUAGE plpythonu;
565+
</programlisting>
566+
567+
An anonymous code block receives no arguments, and whatever value it
568+
might return is discarded. Otherwise it behaves just like a function.
569+
</para>
570+
</sect1>
571+
554572
<sect1 id="plpython-trigger">
555573
<title>Trigger Functions</title>
556574

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.576 2010/01/19 14:11:32 mha Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.577 2010/01/22 15:45:15 petere Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201001191
56+
#define CATALOG_VERSION_NO 201001221
5757

5858
#endif

src/include/catalog/pg_pltemplate.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.12 2010/01/05 01:06:56 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.13 2010/01/22 15:45:15 petere Exp $
1212
*
1313
* NOTES
1414
* the genbki.pl script reads this file and generates .bki
@@ -72,8 +72,8 @@ DATA(insert ( "pltcl" t t "pltcl_call_handler" _null_ _null_ "$libdir/pltcl" _n
7272
DATA(insert ( "pltclu" f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
7373
DATA(insert ( "plperl" t t "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ ));
7474
DATA(insert ( "plperlu" f f "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ ));
75-
DATA(insert ( "plpythonu" f f "plpython_call_handler" _null_ _null_ "$libdir/plpython" _null_ ));
76-
DATA(insert ( "plpython2u" f f "plpython_call_handler" _null_ _null_ "$libdir/plpython2" _null_ ));
77-
DATA(insert ( "plpython3u" f f "plpython_call_handler" _null_ _null_ "$libdir/plpython3" _null_ ));
75+
DATA(insert ( "plpythonu" f f "plpython_call_handler" "plpython_inline_handler" _null_ "$libdir/plpython" _null_ ));
76+
DATA(insert ( "plpython2u" f f "plpython_call_handler" "plpython_inline_handler" _null_ "$libdir/plpython2" _null_ ));
77+
DATA(insert ( "plpython3u" f f "plpython_call_handler" "plpython_inline_handler" _null_ "$libdir/plpython3" _null_ ));
7878

7979
#endif /* PG_PLTEMPLATE_H */

src/pl/plpython/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $PostgreSQL: pgsql/src/pl/plpython/Makefile,v 1.35 2009/12/15 22:59:54 petere Exp $
1+
# $PostgreSQL: pgsql/src/pl/plpython/Makefile,v 1.36 2010/01/22 15:45:15 petere Exp $
22

33
subdir = src/pl/plpython
44
top_builddir = ../../..
@@ -66,6 +66,7 @@ REGRESS = \
6666
plpython_schema \
6767
plpython_populate \
6868
plpython_test \
69+
plpython_do \
6970
plpython_global \
7071
plpython_import \
7172
plpython_spi \
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
DO $$ plpy.notice("This is plpythonu.") $$ LANGUAGE plpythonu;
2+
NOTICE: This is plpythonu.
3+
CONTEXT: PL/Python anonymous code block
4+
DO $$ nonsense $$ LANGUAGE plpythonu;
5+
ERROR: PL/Python: NameError: global name 'nonsense' is not defined
6+
CONTEXT: PL/Python anonymous code block

src/pl/plpython/expected/plpython_error.out

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ CREATE FUNCTION exception_index_invalid(text) RETURNS text
2222
'return args[1]'
2323
LANGUAGE plpythonu;
2424
SELECT exception_index_invalid('test');
25-
ERROR: PL/Python: PL/Python function "exception_index_invalid" failed
26-
DETAIL: IndexError: list index out of range
25+
ERROR: PL/Python: IndexError: list index out of range
2726
CONTEXT: PL/Python function "exception_index_invalid"
2827
/* check handling of nested exceptions
2928
*/

src/pl/plpython/plpython.c

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**********************************************************************
22
* plpython.c - python as a procedural language for PostgreSQL
33
*
4-
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.135 2010/01/16 11:03:51 petere Exp $
4+
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.136 2010/01/22 15:45:15 petere Exp $
55
*
66
*********************************************************************
77
*/
@@ -243,14 +243,13 @@ typedef struct PLyResultObject
243243

244244
/* function declarations */
245245

246-
/* Two exported functions: first is the magic telling Postgresql
247-
* what function call interface it implements. Second is for
248-
* initialization of the interpreter during library load.
249-
*/
246+
/* exported functions */
250247
Datum plpython_call_handler(PG_FUNCTION_ARGS);
248+
Datum plpython_inline_handler(PG_FUNCTION_ARGS);
251249
void _PG_init(void);
252250

253251
PG_FUNCTION_INFO_V1(plpython_call_handler);
252+
PG_FUNCTION_INFO_V1(plpython_inline_handler);
254253

255254
/* most of the remaining of the declarations, all static */
256255

@@ -418,6 +417,12 @@ plpython_error_callback(void *arg)
418417
errcontext("PL/Python function \"%s\"", PLy_procedure_name(PLy_curr_procedure));
419418
}
420419

420+
static void
421+
plpython_inline_error_callback(void *arg)
422+
{
423+
errcontext("PL/Python anonymous code block");
424+
}
425+
421426
static void
422427
plpython_trigger_error_callback(void *arg)
423428
{
@@ -495,6 +500,60 @@ plpython_call_handler(PG_FUNCTION_ARGS)
495500
return retval;
496501
}
497502

503+
Datum
504+
plpython_inline_handler(PG_FUNCTION_ARGS)
505+
{
506+
InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
507+
FunctionCallInfoData fake_fcinfo;
508+
FmgrInfo flinfo;
509+
PLyProcedure *save_curr_proc;
510+
PLyProcedure *volatile proc = NULL;
511+
ErrorContextCallback plerrcontext;
512+
513+
if (SPI_connect() != SPI_OK_CONNECT)
514+
elog(ERROR, "SPI_connect failed");
515+
516+
save_curr_proc = PLy_curr_procedure;
517+
518+
/*
519+
* Setup error traceback support for ereport()
520+
*/
521+
plerrcontext.callback = plpython_inline_error_callback;
522+
plerrcontext.previous = error_context_stack;
523+
error_context_stack = &plerrcontext;
524+
525+
MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
526+
MemSet(&flinfo, 0, sizeof(flinfo));
527+
fake_fcinfo.flinfo = &flinfo;
528+
flinfo.fn_oid = InvalidOid;
529+
flinfo.fn_mcxt = CurrentMemoryContext;
530+
531+
proc = PLy_malloc0(sizeof(PLyProcedure));
532+
proc->pyname = PLy_strdup("__plpython_inline_block");
533+
proc->result.out.d.typoid = VOIDOID;
534+
535+
PG_TRY();
536+
{
537+
PLy_procedure_compile(proc, codeblock->source_text);
538+
PLy_curr_procedure = proc;
539+
PLy_function_handler(&fake_fcinfo, proc);
540+
}
541+
PG_CATCH();
542+
{
543+
PLy_curr_procedure = save_curr_proc;
544+
PyErr_Clear();
545+
PG_RE_THROW();
546+
}
547+
PG_END_TRY();
548+
549+
/* Pop the error context stack */
550+
error_context_stack = plerrcontext.previous;
551+
552+
PLy_curr_procedure = save_curr_proc;
553+
554+
PG_RETURN_VOID();
555+
}
556+
498557
/* trigger and function sub handlers
499558
*
500559
* the python function is expected to return Py_None if the tuple is
@@ -1107,7 +1166,7 @@ PLy_procedure_call(PLyProcedure *proc, char *kargs, PyObject *vargs)
11071166
if (rv == NULL || PyErr_Occurred())
11081167
{
11091168
Py_XDECREF(rv);
1110-
PLy_elog(ERROR, "PL/Python function \"%s\" failed", proc->proname);
1169+
PLy_elog(ERROR, NULL);
11111170
}
11121171

11131172
return rv;

src/pl/plpython/sql/plpython_do.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DO $$ plpy.notice("This is plpythonu.") $$ LANGUAGE plpythonu;
2+
3+
DO $$ nonsense $$ LANGUAGE plpythonu;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy