Refactor PLy_spi_prepare to save two levels of indentation
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 24 Jan 2011 20:12:01 +0000 (22:12 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 24 Jan 2011 20:13:06 +0000 (22:13 +0200)
Instead of checking whether the arglist is NULL and then if its length
is 0, do it in one step, and outside of the try/catch block.

Jan UrbaƄski

src/pl/plpython/plpython.c

index 947d3e63f9283a7333ba2a3b5e5f71e909b5d32f..cb04f12382ea63841b419258eb07f62a6626ac83 100644 (file)
@@ -2817,6 +2817,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
        char       *query;
        void       *tmpplan;
        volatile MemoryContext oldcontext;
+       int                     nargs;
 
        if (!PyArg_ParseTuple(args, "s|O", &query, &list))
        {
@@ -2835,80 +2836,78 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
        if ((plan = (PLyPlanObject *) PLy_plan_new()) == NULL)
                return NULL;
 
+       nargs = list ? PySequence_Length(list) : 0;
+
+       plan->nargs = nargs;
+       plan->types = nargs ? PLy_malloc(sizeof(Oid) * nargs) : NULL;
+       plan->values = nargs ? PLy_malloc(sizeof(Datum) * nargs) : NULL;
+       plan->args = nargs ? PLy_malloc(sizeof(PLyTypeInfo) * nargs) : NULL;
+
        oldcontext = CurrentMemoryContext;
        PG_TRY();
        {
-               if (list != NULL)
+               int     i;
+
+               /*
+                * the other loop might throw an exception, if PLyTypeInfo
+                * member isn't properly initialized the Py_DECREF(plan) will
+                * go boom
+                */
+               for (i = 0; i < nargs; i++)
                {
-                       int                     nargs,
-                                               i;
+                       PLy_typeinfo_init(&plan->args[i]);
+                       plan->values[i] = PointerGetDatum(NULL);
+               }
 
-                       nargs = PySequence_Length(list);
-                       if (nargs > 0)
+               for (i = 0; i < nargs; i++)
+               {
+                       char       *sptr;
+                       HeapTuple       typeTup;
+                       Oid                     typeId;
+                       int32           typmod;
+                       Form_pg_type typeStruct;
+
+                       optr = PySequence_GetItem(list, i);
+                       if (PyString_Check(optr))
+                               sptr = PyString_AsString(optr);
+                       else if (PyUnicode_Check(optr))
+                               sptr = PLyUnicode_AsString(optr);
+                       else
                        {
-                               plan->nargs = nargs;
-                               plan->types = PLy_malloc(sizeof(Oid) * nargs);
-                               plan->values = PLy_malloc(sizeof(Datum) * nargs);
-                               plan->args = PLy_malloc(sizeof(PLyTypeInfo) * nargs);
+                               ereport(ERROR,
+                                               (errmsg("plpy.prepare: type name at ordinal position %d is not a string", i)));
+                               sptr = NULL;    /* keep compiler quiet */
+                       }
 
-                               /*
-                                * the other loop might throw an exception, if PLyTypeInfo
-                                * member isn't properly initialized the Py_DECREF(plan) will
-                                * go boom
-                                */
-                               for (i = 0; i < nargs; i++)
-                               {
-                                       PLy_typeinfo_init(&plan->args[i]);
-                                       plan->values[i] = PointerGetDatum(NULL);
-                               }
+                       /********************************************************
+                        * Resolve argument type names and then look them up by
+                        * oid in the system cache, and remember the required
+                        *information for input conversion.
+                        ********************************************************/
 
-                               for (i = 0; i < nargs; i++)
-                               {
-                                       char       *sptr;
-                                       HeapTuple       typeTup;
-                                       Oid                     typeId;
-                                       int32           typmod;
-                                       Form_pg_type typeStruct;
-
-                                       optr = PySequence_GetItem(list, i);
-                                       if (PyString_Check(optr))
-                                               sptr = PyString_AsString(optr);
-                                       else if (PyUnicode_Check(optr))
-                                               sptr = PLyUnicode_AsString(optr);
-                                       else
-                                       {
-                                               ereport(ERROR,
-                                                               (errmsg("plpy.prepare: type name at ordinal position %d is not a string", i)));
-                                               sptr = NULL;    /* keep compiler quiet */
-                                       }
-
-                                       /********************************************************
-                                        * Resolve argument type names and then look them up by
-                                        * oid in the system cache, and remember the required
-                                        *information for input conversion.
-                                        ********************************************************/
-
-                                       parseTypeString(sptr, &typeId, &typmod);
-
-                                       typeTup = SearchSysCache1(TYPEOID,
-                                                                                         ObjectIdGetDatum(typeId));
-                                       if (!HeapTupleIsValid(typeTup))
-                                               elog(ERROR, "cache lookup failed for type %u", typeId);
-
-                                       Py_DECREF(optr);
-                                       optr = NULL;    /* this is important */
-
-                                       plan->types[i] = typeId;
-                                       typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
-                                       if (typeStruct->typtype != TYPTYPE_COMPOSITE)
-                                               PLy_output_datum_func(&plan->args[i], typeTup);
-                                       else
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                                errmsg("plpy.prepare does not support composite types")));
-                                       ReleaseSysCache(typeTup);
-                               }
-                       }
+                       parseTypeString(sptr, &typeId, &typmod);
+
+                       typeTup = SearchSysCache1(TYPEOID,
+                                                                         ObjectIdGetDatum(typeId));
+                       if (!HeapTupleIsValid(typeTup))
+                               elog(ERROR, "cache lookup failed for type %u", typeId);
+
+                       Py_DECREF(optr);
+                       /*
+                        * set optr to NULL, so we won't try to unref it again in
+                        * case of an error
+                        */
+                       optr = NULL;
+
+                       plan->types[i] = typeId;
+                       typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
+                       if (typeStruct->typtype != TYPTYPE_COMPOSITE)
+                               PLy_output_datum_func(&plan->args[i], typeTup);
+                       else
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                                errmsg("plpy.prepare does not support composite types")));
+                       ReleaseSysCache(typeTup);
                }
 
                pg_verifymbstr(query, strlen(query), false);
@@ -2943,6 +2942,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
        }
        PG_END_TRY();
 
+       Assert(plan->plan != NULL);
        return (PyObject *) plan;
 }