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