1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

PL/Python: Fix crash when colnames() etc. called without result set

The result object methods colnames() etc. would crash when called
after a command that did not produce a result set.  Now they throw an
exception.

discovery and initial patch by Jean-Baptiste Quenot
This commit is contained in:
Peter Eisentraut
2012-04-15 20:23:08 +03:00
parent 4efbb7d04f
commit c03523ed3f
4 changed files with 49 additions and 13 deletions

View File

@ -115,9 +115,9 @@ SELECT join_sequences(sequences) FROM sequences
--
-- plan and result objects
--
CREATE FUNCTION result_nrows_test() RETURNS int
CREATE FUNCTION result_metadata_test(cmd text) RETURNS int
AS $$
plan = plpy.prepare("SELECT 1 AS foo, '11'::text AS bar UNION SELECT 2, '22'")
plan = plpy.prepare(cmd)
plpy.info(plan.status()) # not really documented or useful
result = plpy.execute(plan)
if result.status() > 0:
@ -128,20 +128,28 @@ if result.status() > 0:
else:
return None
$$ LANGUAGE plpythonu;
SELECT result_nrows_test();
SELECT result_metadata_test($$SELECT 1 AS foo, '11'::text AS bar UNION SELECT 2, '22'$$);
INFO: True
CONTEXT: PL/Python function "result_nrows_test"
CONTEXT: PL/Python function "result_metadata_test"
INFO: ['foo', 'bar']
CONTEXT: PL/Python function "result_nrows_test"
CONTEXT: PL/Python function "result_metadata_test"
INFO: [23, 25]
CONTEXT: PL/Python function "result_nrows_test"
CONTEXT: PL/Python function "result_metadata_test"
INFO: [-1, -1]
CONTEXT: PL/Python function "result_nrows_test"
result_nrows_test
-------------------
2
CONTEXT: PL/Python function "result_metadata_test"
result_metadata_test
----------------------
2
(1 row)
SELECT result_metadata_test($$CREATE TEMPORARY TABLE foo1 (a int, b text)$$);
INFO: True
CONTEXT: PL/Python function "result_metadata_test"
ERROR: plpy.Error: command did not produce a result set
CONTEXT: Traceback (most recent call last):
PL/Python function "result_metadata_test", line 6, in <module>
plpy.info(result.colnames())
PL/Python function "result_metadata_test"
-- cursor objects
CREATE FUNCTION simple_cursor_test() RETURNS int AS $$
res = plpy.cursor("select fname, lname from users")

View File

@ -9,6 +9,7 @@
#include "plpython.h"
#include "plpy_resultobject.h"
#include "plpy_elog.h"
static void PLy_result_dealloc(PyObject *arg);
@ -131,6 +132,12 @@ PLy_result_colnames(PyObject *self, PyObject *unused)
PyObject *list;
int i;
if (!ob->tupdesc)
{
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
return NULL;
}
list = PyList_New(ob->tupdesc->natts);
for (i = 0; i < ob->tupdesc->natts; i++)
PyList_SET_ITEM(list, i, PyString_FromString(NameStr(ob->tupdesc->attrs[i]->attname)));
@ -145,6 +152,12 @@ PLy_result_coltypes(PyObject *self, PyObject *unused)
PyObject *list;
int i;
if (!ob->tupdesc)
{
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
return NULL;
}
list = PyList_New(ob->tupdesc->natts);
for (i = 0; i < ob->tupdesc->natts; i++)
PyList_SET_ITEM(list, i, PyInt_FromLong(ob->tupdesc->attrs[i]->atttypid));
@ -159,6 +172,12 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused)
PyObject *list;
int i;
if (!ob->tupdesc)
{
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
return NULL;
}
list = PyList_New(ob->tupdesc->natts);
for (i = 0; i < ob->tupdesc->natts; i++)
PyList_SET_ITEM(list, i, PyInt_FromLong(ob->tupdesc->attrs[i]->atttypmod));

View File

@ -93,9 +93,9 @@ SELECT join_sequences(sequences) FROM sequences
-- plan and result objects
--
CREATE FUNCTION result_nrows_test() RETURNS int
CREATE FUNCTION result_metadata_test(cmd text) RETURNS int
AS $$
plan = plpy.prepare("SELECT 1 AS foo, '11'::text AS bar UNION SELECT 2, '22'")
plan = plpy.prepare(cmd)
plpy.info(plan.status()) # not really documented or useful
result = plpy.execute(plan)
if result.status() > 0:
@ -107,7 +107,8 @@ else:
return None
$$ LANGUAGE plpythonu;
SELECT result_nrows_test();
SELECT result_metadata_test($$SELECT 1 AS foo, '11'::text AS bar UNION SELECT 2, '22'$$);
SELECT result_metadata_test($$CREATE TEMPORARY TABLE foo1 (a int, b text)$$);
-- cursor objects