diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index a722fce917bace91b3b796339a35793bd7c67eae..dc36c9f88795636d15b10c3e7ff5822e08762a6d 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -1,7 +1,7 @@ /********************************************************************** * plpython.c - python as a procedural language for PostgreSQL * - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.78 2006/04/27 01:05:05 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.79 2006/04/27 14:18:07 momjian Exp $ * ********************************************************************* */ @@ -19,7 +19,6 @@ #include "catalog/pg_type.h" #include "commands/trigger.h" #include "executor/spi.h" -#include "funcapi.h" #include "fmgr.h" #include "nodes/makefuncs.h" #include "parser/parse_type.h" @@ -109,11 +108,6 @@ typedef struct PLyProcedure bool fn_readonly; PLyTypeInfo result; /* also used to store info for trigger tuple * type */ - bool is_setof; /* true, if procedure returns result set */ - PyObject *setof; /* contents of result set. */ - int setof_count; /* numbef of items to return in result set */ - int setof_current; /* current item in result set */ - char **argnames; /* Argument names */ PLyTypeInfo args[FUNC_MAX_ARGS]; int nargs; PyObject *code; /* compiled procedure code */ @@ -190,7 +184,6 @@ static Datum PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *); static HeapTuple PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *); static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *); -static void PLy_function_delete_args(PLyProcedure *); static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *, HeapTuple *); static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *, @@ -225,7 +218,6 @@ static PyObject *PLyFloat_FromString(const char *); static PyObject *PLyInt_FromString(const char *); static PyObject *PLyLong_FromString(const char *); static PyObject *PLyString_FromString(const char *); -static HeapTuple PLyDict_ToTuple(PLyTypeInfo *, PyObject *); /* global data */ @@ -734,17 +726,11 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc) PG_TRY(); { - if (!proc->is_setof || proc->setof_count == -1) - { - /* python function not called yet, do it */ - plargs = PLy_function_build_args(fcinfo, proc); - plrv = PLy_procedure_call(proc, "args", plargs); - if (!proc->is_setof) - /* SETOF function parameters are deleted when called last row is returned */ - PLy_function_delete_args(proc); - Assert(plrv != NULL); - Assert(!PLy_error_in_progress); - } + plargs = PLy_function_build_args(fcinfo, proc); + plrv = PLy_procedure_call(proc, "args", plargs); + + Assert(plrv != NULL); + Assert(!PLy_error_in_progress); /* * Disconnect from SPI manager and then create the return values datum @@ -755,76 +741,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc) if (SPI_finish() != SPI_OK_FINISH) elog(ERROR, "SPI_finish failed"); - if (proc->is_setof) - { - bool is_done = false; - ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo; - - if (proc->setof_current == -1) - { - /* first time -- do checks and setup */ - if (!rsi || !IsA(rsi, ReturnSetInfo) || - (rsi->allowedModes & SFRM_ValuePerCall) == 0) - { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("only value per call is allowed"))); - } - rsi->returnMode = SFRM_ValuePerCall; - - /* fetch information about returned object */ - proc->setof = plrv; - plrv = NULL; - if (PyList_Check(proc->setof)) - /* SETOF as list */ - proc->setof_count = PyList_GET_SIZE(proc->setof); - else if (PyIter_Check(proc->setof)) - /* SETOF as iterator, unknown number of items */ - proc->setof_current = proc->setof_count = 0; - else - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("SETOF must be returned as list or iterator"))); - } - } - - Assert(proc->setof != NULL); - - /* Fetch next of SETOF */ - if (PyList_Check(proc->setof)) - { - is_done = ++proc->setof_current == proc->setof_count; - if (!is_done) - plrv = PyList_GET_ITEM(proc->setof, proc->setof_current); - } - else if (PyIter_Check(proc->setof)) - { - plrv = PyIter_Next(proc->setof); - is_done = plrv == NULL; - } - - if (!is_done) - { - rsi->isDone = ExprMultipleResult; - } - else - { - rsi->isDone = ExprEndResult; - proc->setof_count = proc->setof_current = -1; - Py_DECREF(proc->setof); - proc->setof = NULL; - - Py_XDECREF(plargs); - Py_XDECREF(plrv); - Py_XDECREF(plrv_so); - - PLy_function_delete_args(proc); - fcinfo->isnull = true; - return (Datum)NULL; - } - } - /* * If the function is declared to return void, the Python * return value must be None. For void-returning functions, we @@ -851,26 +767,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc) proc->result.out.d.typioparam, -1); } - else if (proc->result.is_rowtype >= 1) - { - HeapTuple tuple; - - /* returning composite type */ - if (!PyDict_Check(plrv)) - elog(ERROR, "tuple must be returned as dictionary"); - - tuple = PLyDict_ToTuple(&proc->result, plrv); - if (tuple != NULL) - { - fcinfo->isnull = false; - rv = HeapTupleGetDatum(tuple); - } - else - { - fcinfo->isnull = true; - rv = (Datum) NULL; - } - } else { fcinfo->isnull = false; @@ -997,7 +893,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) * FIXME -- error check this */ PyList_SetItem(args, i, arg); - PyDict_SetItemString(proc->globals, proc->argnames[i], arg); arg = NULL; } } @@ -1014,16 +909,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) } -static void -PLy_function_delete_args(PLyProcedure *proc) -{ - int i; - - for (i = 0; i < proc->nargs; i++) - PyDict_DelItemString(proc->globals, proc->argnames[i]); -} - - /* * PLyProcedure functions */ @@ -1094,9 +979,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, bool isnull; int i, rv; - Datum argnames; - Datum *elems; - int nelems; procStruct = (Form_pg_proc) GETSTRUCT(procTup); @@ -1128,10 +1010,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, proc->nargs = 0; proc->code = proc->statics = NULL; proc->globals = proc->me = NULL; - proc->is_setof = procStruct->proretset; - proc->setof = NULL; - proc->setof_count = proc->setof_current = -1; - proc->argnames = NULL; PG_TRY(); { @@ -1168,11 +1046,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, } if (rvTypeStruct->typtype == 'c') - { - /* Tuple: set up later, during first call to PLy_function_handler */ - proc->result.out.d.typoid = procStruct->prorettype; - proc->result.is_rowtype = 2; - } + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("plpython functions cannot return tuples yet"))); else PLy_output_datum_func(&proc->result, rvTypeTup); @@ -1195,21 +1071,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, * arguments. */ proc->nargs = fcinfo->nargs; - proc->argnames = NULL; - if (proc->nargs) - { - argnames = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames, &isnull); - if (!isnull) - { - deconstruct_array(DatumGetArrayTypeP(argnames), TEXTOID, -1, false, 'i', - &elems, NULL, &nelems); - if (nelems != proc->nargs) - elog(ERROR, - "proargnames must have the same number of elements " - "as the function has arguments"); - proc->argnames = (char **) PLy_malloc(sizeof(char *)*proc->nargs); - } - } for (i = 0; i < fcinfo->nargs; i++) { HeapTuple argTypeTup; @@ -1238,12 +1099,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, proc->args[i].is_rowtype = 2; /* still need to set I/O funcs */ ReleaseSysCache(argTypeTup); - - /* Fetch argument name */ - if (proc->argnames) - proc->argnames[i] = PLy_strdup(DatumGetCString(DirectFunctionCall1(textout, elems[i]))); } + /* * get the text of the function. */ @@ -1378,7 +1236,6 @@ PLy_procedure_delete(PLyProcedure * proc) if (proc->pyname) PLy_free(proc->pyname); for (i = 0; i < proc->nargs; i++) - { if (proc->args[i].is_rowtype == 1) { if (proc->args[i].in.r.atts) @@ -1386,11 +1243,6 @@ PLy_procedure_delete(PLyProcedure * proc) if (proc->args[i].out.r.atts) PLy_free(proc->args[i].out.r.atts); } - if (proc->argnames && proc->argnames[i]) - PLy_free(proc->argnames[i]); - } - if (proc->argnames) - PLy_free(proc->argnames); } /* conversion functions. remember output from python is @@ -1649,78 +1501,6 @@ PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc) return dict; } - -static HeapTuple -PLyDict_ToTuple(PLyTypeInfo *info, PyObject *dict) -{ - TupleDesc desc; - HeapTuple tuple; - Datum *values; - char *nulls; - int i; - - desc = CreateTupleDescCopy(lookup_rowtype_tupdesc(info->out.d.typoid, -1)); - - /* Set up tuple type, if neccessary */ - if (info->is_rowtype == 2) - { - PLy_output_tuple_funcs(info, desc); - info->is_rowtype = 1; - } - Assert(info->is_rowtype == 1); - - /* Build tuple */ - values = palloc(sizeof(Datum)*desc->natts); - nulls = palloc(sizeof(char)*desc->natts); - for (i = 0; i < desc->natts; ++i) - { - char *key; - PyObject *value, - *so; - - key = NameStr(desc->attrs[i]->attname); - value = so = NULL; - PG_TRY(); - { - value = PyDict_GetItemString(dict, key); - if (value != Py_None && value != NULL) - { - char *valuestr; - - so = PyObject_Str(value); - valuestr = PyString_AsString(so); - values[i] = InputFunctionCall(&info->out.r.atts[i].typfunc - , valuestr - , info->out.r.atts[i].typioparam - , -1); - Py_DECREF(so); - value = so = NULL; - nulls[i] = ' '; - } - else - { - value = NULL; - values[i] = (Datum) NULL; - nulls[i] = 'n'; - } - } - PG_CATCH(); - { - Py_XDECREF(value); - Py_XDECREF(so); - PG_RE_THROW(); - } - PG_END_TRY(); - } - - tuple = heap_formtuple(desc, values, nulls); - FreeTupleDesc(desc); - pfree(values); - pfree(nulls); - - return tuple; -} - /* initialization, some python variables function declared here */ /* interface to postgresql elog */ @@ -2864,4 +2644,3 @@ PLy_free(void *ptr) { free(ptr); } -/* vim: set noexpandtab nosmarttab shiftwidth=8 cinoptions=l1j1: */