Skip to content

Commit 203592d

Browse files
committed
Revert patch, causing plpython regression failues:
> >> >> > 1) named parameters additionally to args[] > >> >> > 2) return composite-types from plpython as dictionary > >> >> > 3) return result-set from plpython as list, iterator or generator
1 parent 8f10768 commit 203592d

File tree

1 file changed

+10
-231
lines changed

1 file changed

+10
-231
lines changed

src/pl/plpython/plpython.c

Lines changed: 10 additions & 231 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.78 2006/04/27 01:05:05 momjian Exp $
4+
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.79 2006/04/27 14:18:07 momjian Exp $
55
*
66
*********************************************************************
77
*/
@@ -19,7 +19,6 @@
1919
#include "catalog/pg_type.h"
2020
#include "commands/trigger.h"
2121
#include "executor/spi.h"
22-
#include "funcapi.h"
2322
#include "fmgr.h"
2423
#include "nodes/makefuncs.h"
2524
#include "parser/parse_type.h"
@@ -109,11 +108,6 @@ typedef struct PLyProcedure
109108
bool fn_readonly;
110109
PLyTypeInfo result; /* also used to store info for trigger tuple
111110
* type */
112-
bool is_setof; /* true, if procedure returns result set */
113-
PyObject *setof; /* contents of result set. */
114-
int setof_count; /* numbef of items to return in result set */
115-
int setof_current; /* current item in result set */
116-
char **argnames; /* Argument names */
117111
PLyTypeInfo args[FUNC_MAX_ARGS];
118112
int nargs;
119113
PyObject *code; /* compiled procedure code */
@@ -190,7 +184,6 @@ static Datum PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *);
190184
static HeapTuple PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *);
191185

192186
static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *);
193-
static void PLy_function_delete_args(PLyProcedure *);
194187
static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *,
195188
HeapTuple *);
196189
static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *,
@@ -225,7 +218,6 @@ static PyObject *PLyFloat_FromString(const char *);
225218
static PyObject *PLyInt_FromString(const char *);
226219
static PyObject *PLyLong_FromString(const char *);
227220
static PyObject *PLyString_FromString(const char *);
228-
static HeapTuple PLyDict_ToTuple(PLyTypeInfo *, PyObject *);
229221

230222

231223
/* global data */
@@ -734,17 +726,11 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
734726

735727
PG_TRY();
736728
{
737-
if (!proc->is_setof || proc->setof_count == -1)
738-
{
739-
/* python function not called yet, do it */
740-
plargs = PLy_function_build_args(fcinfo, proc);
741-
plrv = PLy_procedure_call(proc, "args", plargs);
742-
if (!proc->is_setof)
743-
/* SETOF function parameters are deleted when called last row is returned */
744-
PLy_function_delete_args(proc);
745-
Assert(plrv != NULL);
746-
Assert(!PLy_error_in_progress);
747-
}
729+
plargs = PLy_function_build_args(fcinfo, proc);
730+
plrv = PLy_procedure_call(proc, "args", plargs);
731+
732+
Assert(plrv != NULL);
733+
Assert(!PLy_error_in_progress);
748734

749735
/*
750736
* Disconnect from SPI manager and then create the return values datum
@@ -755,76 +741,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
755741
if (SPI_finish() != SPI_OK_FINISH)
756742
elog(ERROR, "SPI_finish failed");
757743

758-
if (proc->is_setof)
759-
{
760-
bool is_done = false;
761-
ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
762-
763-
if (proc->setof_current == -1)
764-
{
765-
/* first time -- do checks and setup */
766-
if (!rsi || !IsA(rsi, ReturnSetInfo) ||
767-
(rsi->allowedModes & SFRM_ValuePerCall) == 0)
768-
{
769-
ereport(ERROR,
770-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
771-
errmsg("only value per call is allowed")));
772-
}
773-
rsi->returnMode = SFRM_ValuePerCall;
774-
775-
/* fetch information about returned object */
776-
proc->setof = plrv;
777-
plrv = NULL;
778-
if (PyList_Check(proc->setof))
779-
/* SETOF as list */
780-
proc->setof_count = PyList_GET_SIZE(proc->setof);
781-
else if (PyIter_Check(proc->setof))
782-
/* SETOF as iterator, unknown number of items */
783-
proc->setof_current = proc->setof_count = 0;
784-
else
785-
{
786-
ereport(ERROR,
787-
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
788-
errmsg("SETOF must be returned as list or iterator")));
789-
}
790-
}
791-
792-
Assert(proc->setof != NULL);
793-
794-
/* Fetch next of SETOF */
795-
if (PyList_Check(proc->setof))
796-
{
797-
is_done = ++proc->setof_current == proc->setof_count;
798-
if (!is_done)
799-
plrv = PyList_GET_ITEM(proc->setof, proc->setof_current);
800-
}
801-
else if (PyIter_Check(proc->setof))
802-
{
803-
plrv = PyIter_Next(proc->setof);
804-
is_done = plrv == NULL;
805-
}
806-
807-
if (!is_done)
808-
{
809-
rsi->isDone = ExprMultipleResult;
810-
}
811-
else
812-
{
813-
rsi->isDone = ExprEndResult;
814-
proc->setof_count = proc->setof_current = -1;
815-
Py_DECREF(proc->setof);
816-
proc->setof = NULL;
817-
818-
Py_XDECREF(plargs);
819-
Py_XDECREF(plrv);
820-
Py_XDECREF(plrv_so);
821-
822-
PLy_function_delete_args(proc);
823-
fcinfo->isnull = true;
824-
return (Datum)NULL;
825-
}
826-
}
827-
828744
/*
829745
* If the function is declared to return void, the Python
830746
* return value must be None. For void-returning functions, we
@@ -851,26 +767,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
851767
proc->result.out.d.typioparam,
852768
-1);
853769
}
854-
else if (proc->result.is_rowtype >= 1)
855-
{
856-
HeapTuple tuple;
857-
858-
/* returning composite type */
859-
if (!PyDict_Check(plrv))
860-
elog(ERROR, "tuple must be returned as dictionary");
861-
862-
tuple = PLyDict_ToTuple(&proc->result, plrv);
863-
if (tuple != NULL)
864-
{
865-
fcinfo->isnull = false;
866-
rv = HeapTupleGetDatum(tuple);
867-
}
868-
else
869-
{
870-
fcinfo->isnull = true;
871-
rv = (Datum) NULL;
872-
}
873-
}
874770
else
875771
{
876772
fcinfo->isnull = false;
@@ -997,7 +893,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
997893
* FIXME -- error check this
998894
*/
999895
PyList_SetItem(args, i, arg);
1000-
PyDict_SetItemString(proc->globals, proc->argnames[i], arg);
1001896
arg = NULL;
1002897
}
1003898
}
@@ -1014,16 +909,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
1014909
}
1015910

1016911

1017-
static void
1018-
PLy_function_delete_args(PLyProcedure *proc)
1019-
{
1020-
int i;
1021-
1022-
for (i = 0; i < proc->nargs; i++)
1023-
PyDict_DelItemString(proc->globals, proc->argnames[i]);
1024-
}
1025-
1026-
1027912
/*
1028913
* PLyProcedure functions
1029914
*/
@@ -1094,9 +979,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1094979
bool isnull;
1095980
int i,
1096981
rv;
1097-
Datum argnames;
1098-
Datum *elems;
1099-
int nelems;
1100982

1101983
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1102984

@@ -1128,10 +1010,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
11281010
proc->nargs = 0;
11291011
proc->code = proc->statics = NULL;
11301012
proc->globals = proc->me = NULL;
1131-
proc->is_setof = procStruct->proretset;
1132-
proc->setof = NULL;
1133-
proc->setof_count = proc->setof_current = -1;
1134-
proc->argnames = NULL;
11351013

11361014
PG_TRY();
11371015
{
@@ -1168,11 +1046,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
11681046
}
11691047

11701048
if (rvTypeStruct->typtype == 'c')
1171-
{
1172-
/* Tuple: set up later, during first call to PLy_function_handler */
1173-
proc->result.out.d.typoid = procStruct->prorettype;
1174-
proc->result.is_rowtype = 2;
1175-
}
1049+
ereport(ERROR,
1050+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1051+
errmsg("plpython functions cannot return tuples yet")));
11761052
else
11771053
PLy_output_datum_func(&proc->result, rvTypeTup);
11781054

@@ -1195,21 +1071,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
11951071
* arguments.
11961072
*/
11971073
proc->nargs = fcinfo->nargs;
1198-
proc->argnames = NULL;
1199-
if (proc->nargs)
1200-
{
1201-
argnames = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames, &isnull);
1202-
if (!isnull)
1203-
{
1204-
deconstruct_array(DatumGetArrayTypeP(argnames), TEXTOID, -1, false, 'i',
1205-
&elems, NULL, &nelems);
1206-
if (nelems != proc->nargs)
1207-
elog(ERROR,
1208-
"proargnames must have the same number of elements "
1209-
"as the function has arguments");
1210-
proc->argnames = (char **) PLy_malloc(sizeof(char *)*proc->nargs);
1211-
}
1212-
}
12131074
for (i = 0; i < fcinfo->nargs; i++)
12141075
{
12151076
HeapTuple argTypeTup;
@@ -1238,12 +1099,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
12381099
proc->args[i].is_rowtype = 2; /* still need to set I/O funcs */
12391100

12401101
ReleaseSysCache(argTypeTup);
1241-
1242-
/* Fetch argument name */
1243-
if (proc->argnames)
1244-
proc->argnames[i] = PLy_strdup(DatumGetCString(DirectFunctionCall1(textout, elems[i])));
12451102
}
12461103

1104+
12471105
/*
12481106
* get the text of the function.
12491107
*/
@@ -1378,19 +1236,13 @@ PLy_procedure_delete(PLyProcedure * proc)
13781236
if (proc->pyname)
13791237
PLy_free(proc->pyname);
13801238
for (i = 0; i < proc->nargs; i++)
1381-
{
13821239
if (proc->args[i].is_rowtype == 1)
13831240
{
13841241
if (proc->args[i].in.r.atts)
13851242
PLy_free(proc->args[i].in.r.atts);
13861243
if (proc->args[i].out.r.atts)
13871244
PLy_free(proc->args[i].out.r.atts);
13881245
}
1389-
if (proc->argnames && proc->argnames[i])
1390-
PLy_free(proc->argnames[i]);
1391-
}
1392-
if (proc->argnames)
1393-
PLy_free(proc->argnames);
13941246
}
13951247

13961248
/* conversion functions. remember output from python is
@@ -1649,78 +1501,6 @@ PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc)
16491501
return dict;
16501502
}
16511503

1652-
1653-
static HeapTuple
1654-
PLyDict_ToTuple(PLyTypeInfo *info, PyObject *dict)
1655-
{
1656-
TupleDesc desc;
1657-
HeapTuple tuple;
1658-
Datum *values;
1659-
char *nulls;
1660-
int i;
1661-
1662-
desc = CreateTupleDescCopy(lookup_rowtype_tupdesc(info->out.d.typoid, -1));
1663-
1664-
/* Set up tuple type, if neccessary */
1665-
if (info->is_rowtype == 2)
1666-
{
1667-
PLy_output_tuple_funcs(info, desc);
1668-
info->is_rowtype = 1;
1669-
}
1670-
Assert(info->is_rowtype == 1);
1671-
1672-
/* Build tuple */
1673-
values = palloc(sizeof(Datum)*desc->natts);
1674-
nulls = palloc(sizeof(char)*desc->natts);
1675-
for (i = 0; i < desc->natts; ++i)
1676-
{
1677-
char *key;
1678-
PyObject *value,
1679-
*so;
1680-
1681-
key = NameStr(desc->attrs[i]->attname);
1682-
value = so = NULL;
1683-
PG_TRY();
1684-
{
1685-
value = PyDict_GetItemString(dict, key);
1686-
if (value != Py_None && value != NULL)
1687-
{
1688-
char *valuestr;
1689-
1690-
so = PyObject_Str(value);
1691-
valuestr = PyString_AsString(so);
1692-
values[i] = InputFunctionCall(&info->out.r.atts[i].typfunc
1693-
, valuestr
1694-
, info->out.r.atts[i].typioparam
1695-
, -1);
1696-
Py_DECREF(so);
1697-
value = so = NULL;
1698-
nulls[i] = ' ';
1699-
}
1700-
else
1701-
{
1702-
value = NULL;
1703-
values[i] = (Datum) NULL;
1704-
nulls[i] = 'n';
1705-
}
1706-
}
1707-
PG_CATCH();
1708-
{
1709-
Py_XDECREF(value);
1710-
Py_XDECREF(so);
1711-
PG_RE_THROW();
1712-
}
1713-
PG_END_TRY();
1714-
}
1715-
1716-
tuple = heap_formtuple(desc, values, nulls);
1717-
FreeTupleDesc(desc);
1718-
pfree(values);
1719-
pfree(nulls);
1720-
1721-
return tuple;
1722-
}
1723-
17241504
/* initialization, some python variables function declared here */
17251505

17261506
/* interface to postgresql elog */
@@ -2864,4 +2644,3 @@ PLy_free(void *ptr)
28642644
{
28652645
free(ptr);
28662646
}
2867-
/* vim: set noexpandtab nosmarttab shiftwidth=8 cinoptions=l1j1: */

0 commit comments

Comments
 (0)