@@ -2817,6 +2817,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
28172817char * query ;
28182818void * tmpplan ;
28192819volatile MemoryContext oldcontext ;
2820+ int nargs ;
28202821
28212822if (!PyArg_ParseTuple (args ,"s|O" ,& query ,& list ))
28222823{
@@ -2835,80 +2836,78 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
28352836if ((plan = (PLyPlanObject * )PLy_plan_new ())== NULL )
28362837return NULL ;
28372838
2839+ nargs = list ?PySequence_Length (list ) :0 ;
2840+
2841+ plan -> nargs = nargs ;
2842+ plan -> types = nargs ?PLy_malloc (sizeof (Oid )* nargs ) :NULL ;
2843+ plan -> values = nargs ?PLy_malloc (sizeof (Datum )* nargs ) :NULL ;
2844+ plan -> args = nargs ?PLy_malloc (sizeof (PLyTypeInfo )* nargs ) :NULL ;
2845+
28382846oldcontext = CurrentMemoryContext ;
28392847PG_TRY ();
28402848{
2841- if (list != NULL )
2849+ int i ;
2850+
2851+ /*
2852+ * the other loop might throw an exception, if PLyTypeInfo
2853+ * member isn't properly initialized the Py_DECREF(plan) will
2854+ * go boom
2855+ */
2856+ for (i = 0 ;i < nargs ;i ++ )
28422857{
2843- int nargs ,
2844- i ;
2858+ PLy_typeinfo_init (& plan -> args [i ]);
2859+ plan -> values [i ]= PointerGetDatum (NULL );
2860+ }
28452861
2846- nargs = PySequence_Length (list );
2847- if (nargs > 0 )
2862+ for (i = 0 ;i < nargs ;i ++ )
2863+ {
2864+ char * sptr ;
2865+ HeapTuple typeTup ;
2866+ Oid typeId ;
2867+ int32 typmod ;
2868+ Form_pg_type typeStruct ;
2869+
2870+ optr = PySequence_GetItem (list ,i );
2871+ if (PyString_Check (optr ))
2872+ sptr = PyString_AsString (optr );
2873+ else if (PyUnicode_Check (optr ))
2874+ sptr = PLyUnicode_AsString (optr );
2875+ else
28482876{
2849- plan -> nargs = nargs ;
2850- plan -> types = PLy_malloc ( sizeof ( Oid ) * nargs );
2851- plan -> values = PLy_malloc ( sizeof ( Datum ) * nargs );
2852- plan -> args = PLy_malloc ( sizeof ( PLyTypeInfo ) * nargs );
2877+ ereport ( ERROR ,
2878+ ( errmsg ( "plpy.prepare: type name at ordinal position %d is not a string" , i )) );
2879+ sptr = NULL ; /* keep compiler quiet */
2880+ }
28532881
2854- /*
2855- * the other loop might throw an exception, if PLyTypeInfo
2856- * member isn't properly initialized the Py_DECREF(plan) will
2857- * go boom
2858- */
2859- for (i = 0 ;i < nargs ;i ++ )
2860- {
2861- PLy_typeinfo_init (& plan -> args [i ]);
2862- plan -> values [i ]= PointerGetDatum (NULL );
2863- }
2882+ /********************************************************
2883+ * Resolve argument type names and then look them up by
2884+ * oid in the system cache, and remember the required
2885+ *information for input conversion.
2886+ ********************************************************/
28642887
2865- for (i = 0 ;i < nargs ;i ++ )
2866- {
2867- char * sptr ;
2868- HeapTuple typeTup ;
2869- Oid typeId ;
2870- int32 typmod ;
2871- Form_pg_type typeStruct ;
2872-
2873- optr = PySequence_GetItem (list ,i );
2874- if (PyString_Check (optr ))
2875- sptr = PyString_AsString (optr );
2876- else if (PyUnicode_Check (optr ))
2877- sptr = PLyUnicode_AsString (optr );
2878- else
2879- {
2880- ereport (ERROR ,
2881- (errmsg ("plpy.prepare: type name at ordinal position %d is not a string" ,i )));
2882- sptr = NULL ;/* keep compiler quiet */
2883- }
2884-
2885- /********************************************************
2886- * Resolve argument type names and then look them up by
2887- * oid in the system cache, and remember the required
2888- *information for input conversion.
2889- ********************************************************/
2890-
2891- parseTypeString (sptr ,& typeId ,& typmod );
2892-
2893- typeTup = SearchSysCache1 (TYPEOID ,
2894- ObjectIdGetDatum (typeId ));
2895- if (!HeapTupleIsValid (typeTup ))
2896- elog (ERROR ,"cache lookup failed for type %u" ,typeId );
2897-
2898- Py_DECREF (optr );
2899- optr = NULL ;/* this is important */
2900-
2901- plan -> types [i ]= typeId ;
2902- typeStruct = (Form_pg_type )GETSTRUCT (typeTup );
2903- if (typeStruct -> typtype != TYPTYPE_COMPOSITE )
2904- PLy_output_datum_func (& plan -> args [i ],typeTup );
2905- else
2906- ereport (ERROR ,
2907- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2908- errmsg ("plpy.prepare does not support composite types" )));
2909- ReleaseSysCache (typeTup );
2910- }
2911- }
2888+ parseTypeString (sptr ,& typeId ,& typmod );
2889+
2890+ typeTup = SearchSysCache1 (TYPEOID ,
2891+ ObjectIdGetDatum (typeId ));
2892+ if (!HeapTupleIsValid (typeTup ))
2893+ elog (ERROR ,"cache lookup failed for type %u" ,typeId );
2894+
2895+ Py_DECREF (optr );
2896+ /*
2897+ * set optr to NULL, so we won't try to unref it again in
2898+ * case of an error
2899+ */
2900+ optr = NULL ;
2901+
2902+ plan -> types [i ]= typeId ;
2903+ typeStruct = (Form_pg_type )GETSTRUCT (typeTup );
2904+ if (typeStruct -> typtype != TYPTYPE_COMPOSITE )
2905+ PLy_output_datum_func (& plan -> args [i ],typeTup );
2906+ else
2907+ ereport (ERROR ,
2908+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2909+ errmsg ("plpy.prepare does not support composite types" )));
2910+ ReleaseSysCache (typeTup );
29122911}
29132912
29142913pg_verifymbstr (query ,strlen (query ), false);
@@ -2943,6 +2942,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
29432942}
29442943PG_END_TRY ();
29452944
2945+ Assert (plan -> plan != NULL );
29462946return (PyObject * )plan ;
29472947}
29482948