1
1
/**********************************************************************
2
2
* plpython.c - python as a procedural language for PostgreSQL
3
3
*
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 $
5
5
*
6
6
*********************************************************************
7
7
*/
19
19
#include "catalog/pg_type.h"
20
20
#include "commands/trigger.h"
21
21
#include "executor/spi.h"
22
- #include "funcapi.h"
23
22
#include "fmgr.h"
24
23
#include "nodes/makefuncs.h"
25
24
#include "parser/parse_type.h"
@@ -109,11 +108,6 @@ typedef struct PLyProcedure
109
108
bool fn_readonly ;
110
109
PLyTypeInfo result ; /* also used to store info for trigger tuple
111
110
* 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 */
117
111
PLyTypeInfo args [FUNC_MAX_ARGS ];
118
112
int nargs ;
119
113
PyObject * code ; /* compiled procedure code */
@@ -190,7 +184,6 @@ static Datum PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *);
190
184
static HeapTuple PLy_trigger_handler (FunctionCallInfo fcinfo , PLyProcedure * );
191
185
192
186
static PyObject * PLy_function_build_args (FunctionCallInfo fcinfo , PLyProcedure * );
193
- static void PLy_function_delete_args (PLyProcedure * );
194
187
static PyObject * PLy_trigger_build_args (FunctionCallInfo fcinfo , PLyProcedure * ,
195
188
HeapTuple * );
196
189
static HeapTuple PLy_modify_tuple (PLyProcedure * , PyObject * ,
@@ -225,7 +218,6 @@ static PyObject *PLyFloat_FromString(const char *);
225
218
static PyObject * PLyInt_FromString (const char * );
226
219
static PyObject * PLyLong_FromString (const char * );
227
220
static PyObject * PLyString_FromString (const char * );
228
- static HeapTuple PLyDict_ToTuple (PLyTypeInfo * , PyObject * );
229
221
230
222
231
223
/* global data */
@@ -734,17 +726,11 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
734
726
735
727
PG_TRY ();
736
728
{
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 );
748
734
749
735
/*
750
736
* Disconnect from SPI manager and then create the return values datum
@@ -755,76 +741,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
755
741
if (SPI_finish () != SPI_OK_FINISH )
756
742
elog (ERROR , "SPI_finish failed" );
757
743
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
-
828
744
/*
829
745
* If the function is declared to return void, the Python
830
746
* return value must be None. For void-returning functions, we
@@ -851,26 +767,6 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc)
851
767
proc -> result .out .d .typioparam ,
852
768
-1 );
853
769
}
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
- }
874
770
else
875
771
{
876
772
fcinfo -> isnull = false;
@@ -997,7 +893,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
997
893
* FIXME -- error check this
998
894
*/
999
895
PyList_SetItem (args , i , arg );
1000
- PyDict_SetItemString (proc -> globals , proc -> argnames [i ], arg );
1001
896
arg = NULL ;
1002
897
}
1003
898
}
@@ -1014,16 +909,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
1014
909
}
1015
910
1016
911
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
-
1027
912
/*
1028
913
* PLyProcedure functions
1029
914
*/
@@ -1094,9 +979,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1094
979
bool isnull ;
1095
980
int i ,
1096
981
rv ;
1097
- Datum argnames ;
1098
- Datum * elems ;
1099
- int nelems ;
1100
982
1101
983
procStruct = (Form_pg_proc ) GETSTRUCT (procTup );
1102
984
@@ -1128,10 +1010,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1128
1010
proc -> nargs = 0 ;
1129
1011
proc -> code = proc -> statics = NULL ;
1130
1012
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 ;
1135
1013
1136
1014
PG_TRY ();
1137
1015
{
@@ -1168,11 +1046,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1168
1046
}
1169
1047
1170
1048
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" )));
1176
1052
else
1177
1053
PLy_output_datum_func (& proc -> result , rvTypeTup );
1178
1054
@@ -1195,21 +1071,6 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1195
1071
* arguments.
1196
1072
*/
1197
1073
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
- }
1213
1074
for (i = 0 ; i < fcinfo -> nargs ; i ++ )
1214
1075
{
1215
1076
HeapTuple argTypeTup ;
@@ -1238,12 +1099,9 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
1238
1099
proc -> args [i ].is_rowtype = 2 ; /* still need to set I/O funcs */
1239
1100
1240
1101
ReleaseSysCache (argTypeTup );
1241
-
1242
- /* Fetch argument name */
1243
- if (proc -> argnames )
1244
- proc -> argnames [i ] = PLy_strdup (DatumGetCString (DirectFunctionCall1 (textout , elems [i ])));
1245
1102
}
1246
1103
1104
+
1247
1105
/*
1248
1106
* get the text of the function.
1249
1107
*/
@@ -1378,19 +1236,13 @@ PLy_procedure_delete(PLyProcedure * proc)
1378
1236
if (proc -> pyname )
1379
1237
PLy_free (proc -> pyname );
1380
1238
for (i = 0 ; i < proc -> nargs ; i ++ )
1381
- {
1382
1239
if (proc -> args [i ].is_rowtype == 1 )
1383
1240
{
1384
1241
if (proc -> args [i ].in .r .atts )
1385
1242
PLy_free (proc -> args [i ].in .r .atts );
1386
1243
if (proc -> args [i ].out .r .atts )
1387
1244
PLy_free (proc -> args [i ].out .r .atts );
1388
1245
}
1389
- if (proc -> argnames && proc -> argnames [i ])
1390
- PLy_free (proc -> argnames [i ]);
1391
- }
1392
- if (proc -> argnames )
1393
- PLy_free (proc -> argnames );
1394
1246
}
1395
1247
1396
1248
/* conversion functions. remember output from python is
@@ -1649,78 +1501,6 @@ PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc)
1649
1501
return dict ;
1650
1502
}
1651
1503
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
-
1724
1504
/* initialization, some python variables function declared here */
1725
1505
1726
1506
/* interface to postgresql elog */
@@ -2864,4 +2644,3 @@ PLy_free(void *ptr)
2864
2644
{
2865
2645
free (ptr );
2866
2646
}
2867
- /* vim: set noexpandtab nosmarttab shiftwidth=8 cinoptions=l1j1: */
0 commit comments