@@ -2817,6 +2817,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
2817
2817
char * query ;
2818
2818
void * tmpplan ;
2819
2819
volatile MemoryContext oldcontext ;
2820
+ int nargs ;
2820
2821
2821
2822
if (!PyArg_ParseTuple (args , "s|O" , & query , & list ))
2822
2823
{
@@ -2835,80 +2836,78 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
2835
2836
if ((plan = (PLyPlanObject * ) PLy_plan_new ()) == NULL )
2836
2837
return NULL ;
2837
2838
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
+
2838
2846
oldcontext = CurrentMemoryContext ;
2839
2847
PG_TRY ();
2840
2848
{
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 ++ )
2842
2857
{
2843
- int nargs ,
2844
- i ;
2858
+ PLy_typeinfo_init (& plan -> args [i ]);
2859
+ plan -> values [i ] = PointerGetDatum (NULL );
2860
+ }
2845
2861
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
2848
2876
{
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
+ }
2853
2881
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
+ ********************************************************/
2864
2887
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 );
2912
2911
}
2913
2912
2914
2913
pg_verifymbstr (query , strlen (query ), false);
@@ -2943,6 +2942,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
2943
2942
}
2944
2943
PG_END_TRY ();
2945
2944
2945
+ Assert (plan -> plan != NULL );
2946
2946
return (PyObject * ) plan ;
2947
2947
}
2948
2948
0 commit comments