Commit dfdae5d6 authored by Tom Lane's avatar Tom Lane

Hook up the plpython result-object nrows and status methods correctly.

Adjust documentation to match current reality.
parent ff5a354e
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.24 2004/09/13 20:05:18 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.25 2004/12/17 02:14:44 tgl Exp $ -->
<chapter id="plpython"> <chapter id="plpython">
<title>PL/Python - Python Procedural Language</title> <title>PL/Python - Python Procedural Language</title>
...@@ -46,7 +46,8 @@ ...@@ -46,7 +46,8 @@
<title>PL/Python Functions</title> <title>PL/Python Functions</title>
<para> <para>
The Python code you write gets transformed into a Python function. E.g., The Python code you write gets transformed into a Python function.
For example,
<programlisting> <programlisting>
CREATE FUNCTION myfunc(text) RETURNS text CREATE FUNCTION myfunc(text) RETURNS text
AS 'return args[0]' AS 'return args[0]'
...@@ -60,13 +61,14 @@ def __plpython_procedure_myfunc_23456(): ...@@ -60,13 +61,14 @@ def __plpython_procedure_myfunc_23456():
return args[0] return args[0]
</programlisting> </programlisting>
assuming that 23456 is the OID of the function. assuming that 23456 is the OID assigned to the function by
<productname>PostgreSQL</productname>.
</para> </para>
<para> <para>
If you do not provide a return value, Python returns the default If you do not provide a return value, Python returns the default
<symbol>None</symbol>. The language module translates Python's <symbol>None</symbol>. <application>PL/Python</application> translates
<symbol>None</symbol> into the SQL null Python's <symbol>None</symbol> into the SQL null
value.<indexterm><primary>null value</><secondary value.<indexterm><primary>null value</><secondary
sortas="PL/Python">in PL/Python</></indexterm> sortas="PL/Python">in PL/Python</></indexterm>
</para> </para>
...@@ -108,7 +110,7 @@ def __plpython_procedure_myfunc_23456(): ...@@ -108,7 +110,7 @@ def __plpython_procedure_myfunc_23456():
</indexterm> </indexterm>
<para> <para>
When a function is used in a trigger, the dictionary When a function is used as a trigger, the dictionary
<literal>TD</literal> contains trigger-related values. The trigger <literal>TD</literal> contains trigger-related values. The trigger
rows are in <literal>TD["new"]</> and/or <literal>TD["old"]</> rows are in <literal>TD["new"]</> and/or <literal>TD["old"]</>
depending on the trigger event. <literal>TD["event"]</> contains depending on the trigger event. <literal>TD["event"]</> contains
...@@ -120,9 +122,9 @@ def __plpython_procedure_myfunc_23456(): ...@@ -120,9 +122,9 @@ def __plpython_procedure_myfunc_23456():
<literal>STATEMENT</>, and <literal>UNKNOWN</>. <literal>STATEMENT</>, and <literal>UNKNOWN</>.
<literal>TD["name"]</> contains the trigger name, and <literal>TD["name"]</> contains the trigger name, and
<literal>TD["relid"]</> contains the OID of the table on <literal>TD["relid"]</> contains the OID of the table on
which the trigger occurred. If the trigger was called with which the trigger occurred. If the <command>CREATE TRIGGER</> command
arguments they are available in <literal>TD["args"][0]</> to included arguments, they are available in <literal>TD["args"][0]</> to
<literal>TD["args"][(n-1)]</>. <literal>TD["args"][(<replaceable>n</>-1)]</>.
</para> </para>
<para> <para>
...@@ -143,23 +145,23 @@ def __plpython_procedure_myfunc_23456(): ...@@ -143,23 +145,23 @@ def __plpython_procedure_myfunc_23456():
this module are available to you in the Python code as this module are available to you in the Python code as
<literal>plpy.<replaceable>foo</replaceable></literal>. At present <literal>plpy.<replaceable>foo</replaceable></literal>. At present
<literal>plpy</literal> implements the functions <literal>plpy</literal> implements the functions
<literal>plpy.debug("msg")</literal>, <literal>plpy.debug(<replaceable>msg</>)</literal>,
<literal>plpy.log("msg")</literal>, <literal>plpy.log(<replaceable>msg</>)</literal>,
<literal>plpy.info("msg")</literal>, <literal>plpy.info(<replaceable>msg</>)</literal>,
<literal>plpy.notice("msg")</literal>, <literal>plpy.notice(<replaceable>msg</>)</literal>,
<literal>plpy.warning("msg")</literal>, <literal>plpy.warning(<replaceable>msg</>)</literal>,
<literal>plpy.error("msg")</literal>, and <literal>plpy.error(<replaceable>msg</>)</literal>, and
<literal>plpy.fatal("msg")</literal>. They are mostly equivalent <literal>plpy.fatal(<replaceable>msg</>)</literal>.
to calling <literal>elog(<replaceable>LEVEL</>, "msg")</literal> These are mostly equivalent to calling
<literal>elog(<replaceable>level</>, <replaceable>msg</>)</literal>
from C code.<indexterm><primary>elog</><secondary>in from C code.<indexterm><primary>elog</><secondary>in
PL/Python</></indexterm> <function>plpy.error</function> and PL/Python</></indexterm> <function>plpy.error</function> and
<function>plpy.fatal</function> actually raise a Python exception <function>plpy.fatal</function> actually raise a Python exception
which, if uncaught, causes the PL/Python module to call which, if uncaught, causes the PL/Python module to call
<literal>elog(ERROR, msg)</literal> when the function handler <literal>elog(ERROR, msg)</literal> when the function handler
returns from the Python interpreter. Long-jumping out of the returns from the Python interpreter. <literal>raise
Python interpreter is probably not good. <literal>raise plpy.ERROR(<replaceable>msg</>)</literal> and <literal>raise
plpy.ERROR("msg")</literal> and <literal>raise plpy.FATAL(<replaceable>msg</>)</literal> are equivalent to calling
plpy.FATAL("msg")</literal> are equivalent to calling
<function>plpy.error</function> and <function>plpy.error</function> and
<function>plpy.fatal</function>, respectively. <function>plpy.fatal</function>, respectively.
</para> </para>
...@@ -210,17 +212,6 @@ rv = plpy.execute(plan, [ "name" ], 5) ...@@ -210,17 +212,6 @@ rv = plpy.execute(plan, [ "name" ], 5)
The third argument is the limit and is optional. The third argument is the limit and is optional.
</para> </para>
<para>
In the current version, any database error encountered while
running a <application>PL/Python</application> function will result
in the immediate termination of that function by the server; it is
not possible to trap error conditions using Python <literal>try
... catch</literal> constructs. For example, a syntax error in an
SQL statement passed to the <literal>plpy.execute</literal> call
will terminate the function. This behavior may be changed in a
future release.
</para>
<para> <para>
When you prepare a plan using the PL/Python module it is When you prepare a plan using the PL/Python module it is
automatically saved. Read the SPI documentation (<xref automatically saved. Read the SPI documentation (<xref
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.57 2004/09/19 23:38:21 tgl Exp $ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.58 2004/12/17 02:14:48 tgl Exp $
* *
********************************************************************* *********************************************************************
*/ */
...@@ -1531,13 +1531,8 @@ static PyObject *PLy_plan_status(PyObject *, PyObject *); ...@@ -1531,13 +1531,8 @@ static PyObject *PLy_plan_status(PyObject *, PyObject *);
static PyObject *PLy_result_new(void); static PyObject *PLy_result_new(void);
static void PLy_result_dealloc(PyObject *); static void PLy_result_dealloc(PyObject *);
static PyObject *PLy_result_getattr(PyObject *, char *); static PyObject *PLy_result_getattr(PyObject *, char *);
#ifdef NOT_USED
/* Appear to be unused */
static PyObject *PLy_result_fetch(PyObject *, PyObject *);
static PyObject *PLy_result_nrows(PyObject *, PyObject *); static PyObject *PLy_result_nrows(PyObject *, PyObject *);
static PyObject *PLy_result_status(PyObject *, PyObject *); static PyObject *PLy_result_status(PyObject *, PyObject *);
#endif
static int PLy_result_length(PyObject *); static int PLy_result_length(PyObject *);
static PyObject *PLy_result_item(PyObject *, int); static PyObject *PLy_result_item(PyObject *, int);
static PyObject *PLy_result_slice(PyObject *, int, int); static PyObject *PLy_result_slice(PyObject *, int, int);
...@@ -1582,7 +1577,7 @@ static PyTypeObject PLy_PlanType = { ...@@ -1582,7 +1577,7 @@ static PyTypeObject PLy_PlanType = {
}; };
static PyMethodDef PLy_plan_methods[] = { static PyMethodDef PLy_plan_methods[] = {
{"status", (PyCFunction) PLy_plan_status, METH_VARARGS, NULL}, {"status", PLy_plan_status, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
...@@ -1626,15 +1621,11 @@ static PyTypeObject PLy_ResultType = { ...@@ -1626,15 +1621,11 @@ static PyTypeObject PLy_ResultType = {
PLy_result_doc, /* tp_doc */ PLy_result_doc, /* tp_doc */
}; };
#ifdef NOT_USED
/* Appear to be unused */
static PyMethodDef PLy_result_methods[] = { static PyMethodDef PLy_result_methods[] = {
{"fetch", (PyCFunction) PLy_result_fetch, METH_VARARGS, NULL,}, {"nrows", PLy_result_nrows, METH_VARARGS, NULL},
{"nrows", (PyCFunction) PLy_result_nrows, METH_VARARGS, NULL}, {"status", PLy_result_status, METH_VARARGS, NULL},
{"status", (PyCFunction) PLy_result_status, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
#endif
static PyMethodDef PLy_methods[] = { static PyMethodDef PLy_methods[] = {
/* /*
...@@ -1758,17 +1749,9 @@ PLy_result_dealloc(PyObject * arg) ...@@ -1758,17 +1749,9 @@ PLy_result_dealloc(PyObject * arg)
} }
static PyObject * static PyObject *
PLy_result_getattr(PyObject * self, char *attr) PLy_result_getattr(PyObject * self, char *name)
{ {
return NULL; return Py_FindMethod(PLy_result_methods, self, name);
}
#ifdef NOT_USED
/* Appear to be unused */
static PyObject *
PLy_result_fetch(PyObject * self, PyObject * args)
{
return NULL;
} }
static PyObject * static PyObject *
...@@ -1788,7 +1771,6 @@ PLy_result_status(PyObject * self, PyObject * args) ...@@ -1788,7 +1771,6 @@ PLy_result_status(PyObject * self, PyObject * args)
Py_INCREF(ob->status); Py_INCREF(ob->status);
return ob->status; return ob->status;
} }
#endif
static int static int
PLy_result_length(PyObject * arg) PLy_result_length(PyObject * arg)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment