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 */
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 *);
190184static HeapTuple PLy_trigger_handler (FunctionCallInfo fcinfo , PLyProcedure * );
191185
192186static PyObject * PLy_function_build_args (FunctionCallInfo fcinfo , PLyProcedure * );
193- static void PLy_function_delete_args (PLyProcedure * );
194187static PyObject * PLy_trigger_build_args (FunctionCallInfo fcinfo , PLyProcedure * ,
195188 HeapTuple * );
196189static HeapTuple PLy_modify_tuple (PLyProcedure * , PyObject * ,
@@ -225,7 +218,6 @@ static PyObject *PLyFloat_FromString(const char *);
225218static PyObject * PLyInt_FromString (const char * );
226219static PyObject * PLyLong_FromString (const char * );
227220static 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