@@ -2817,6 +2817,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
28172817 char * query ;
28182818 void * tmpplan ;
28192819 volatile MemoryContext oldcontext ;
2820+ int nargs ;
28202821
28212822 if (!PyArg_ParseTuple (args , "s|O" , & query , & list ))
28222823 {
@@ -2835,80 +2836,78 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
28352836 if ((plan = (PLyPlanObject * ) PLy_plan_new ()) == NULL )
28362837 return 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+
28382846 oldcontext = CurrentMemoryContext ;
28392847 PG_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
10BC0
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
29142913 pg_verifymbstr (query , strlen (query ), false);
@@ -2943,6 +2942,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
29432942 }
29442943 PG_END_TRY ();
29452944
2945+ Assert (plan -> plan != NULL );
29462946 return (PyObject * ) plan ;
29472947}
29482948
0 commit comments