From 740e54ca84c437fd67524f97a3ea9ddea752e208 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 20 Jan 2011 21:23:27 +0200 Subject: [PATCH] Factor out functions responsible for caching I/O routines MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This makes PLy_procedure_create a bit more manageable. Jan Urbański --- src/pl/plpython/plpython.c | 245 ++++++++++++++++++++----------------- 1 file changed, 132 insertions(+), 113 deletions(-) diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index d083c6e118..00e3b10ece 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -1385,6 +1385,136 @@ PLy_procedure_get(Oid fn_oid, bool is_trigger) return entry->proc; } +/* + * Set up output conversion functions for a procedure + */ +static void +PLy_procedure_output_conversion(PLyProcedure *proc, Form_pg_proc procStruct) +{ + HeapTuple rvTypeTup; + Form_pg_type rvTypeStruct; + + /* Get the return type */ + rvTypeTup = SearchSysCache1(TYPEOID, + ObjectIdGetDatum(procStruct->prorettype)); + if (!HeapTupleIsValid(rvTypeTup)) + elog(ERROR, "cache lookup failed for type %u", + procStruct->prorettype); + rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup); + + /* Disallow pseudotype result, except for void */ + if (rvTypeStruct->typtype == TYPTYPE_PSEUDO && + procStruct->prorettype != VOIDOID) + { + if (procStruct->prorettype == TRIGGEROID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("trigger functions can only be called as triggers"))); + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("PL/Python functions cannot return type %s", + format_type_be(procStruct->prorettype)))); + } + + if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE) + { + /* + * Tuple: set up later, during first call to + * PLy_function_handler + */ + proc->result.out.d.typoid = procStruct->prorettype; + proc->result.is_rowtype = 2; + } + else + { + /* Do the real work */ + PLy_output_datum_func(&proc->result, rvTypeTup); + } + + ReleaseSysCache(rvTypeTup); +} + +/* + * Set up output conversion functions for a procedure + */ +static void +PLy_procedure_input_conversion(PLyProcedure *proc, HeapTuple procTup, + Form_pg_proc procStruct) +{ + Oid *types; + char **names, + *modes; + int i, + pos, + total; + + /* Extract argument type info from the pg_proc tuple */ + total = get_func_arg_info(procTup, &types, &names, &modes); + + /* Count number of in+inout args into proc->nargs */ + if (modes == NULL) + proc->nargs = total; + else + { + /* proc->nargs was initialized to 0 above */ + for (i = 0; i < total; i++) + { + if (modes[i] != PROARGMODE_OUT && + modes[i] != PROARGMODE_TABLE) + (proc->nargs)++; + } + } + + proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs); + for (i = pos = 0; i < total; i++) + { + HeapTuple argTypeTup; + Form_pg_type argTypeStruct; + + if (modes && + (modes[i] == PROARGMODE_OUT || + modes[i] == PROARGMODE_TABLE)) + continue; /* skip OUT arguments */ + + Assert(types[i] == procStruct->proargtypes.values[pos]); + + argTypeTup = SearchSysCache1(TYPEOID, + ObjectIdGetDatum(types[i])); + if (!HeapTupleIsValid(argTypeTup)) + elog(ERROR, "cache lookup failed for type %u", types[i]); + argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup); + + /* Check argument type is OK, set up I/O function info */ + switch (argTypeStruct->typtype) + { + case TYPTYPE_PSEUDO: + /* Disallow pseudotype argument */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("PL/Python functions cannot accept type %s", + format_type_be(types[i])))); + break; + case TYPTYPE_COMPOSITE: + /* We'll set IO funcs at first call */ + proc->args[pos].is_rowtype = 2; + break; + default: + PLy_input_datum_func(&(proc->args[pos]), + types[i], + argTypeTup); + break; + } + + /* Get argument name */ + proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL; + + ReleaseSysCache(argTypeTup); + + pos++; + } +} + /* * Create a new PLyProcedure structure */ @@ -1433,46 +1563,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) * but only if this isn't a trigger. */ if (!is_trigger) - { - HeapTuple rvTypeTup; - Form_pg_type rvTypeStruct; - - rvTypeTup = SearchSysCache1(TYPEOID, - ObjectIdGetDatum(procStruct->prorettype)); - if (!HeapTupleIsValid(rvTypeTup)) - elog(ERROR, "cache lookup failed for type %u", - procStruct->prorettype); - rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup); - - /* Disallow pseudotype result, except for void */ - if (rvTypeStruct->typtype == TYPTYPE_PSEUDO && - procStruct->prorettype != VOIDOID) - { - if (procStruct->prorettype == TRIGGEROID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("trigger functions can only be called as triggers"))); - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/Python functions cannot return type %s", - format_type_be(procStruct->prorettype)))); - } - - if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE) - { - /* - * Tuple: set up later, during first call to - * PLy_function_handler - */ - proc->result.out.d.typoid = procStruct->prorettype; - proc->result.is_rowtype = 2; - } - else - PLy_output_datum_func(&proc->result, rvTypeTup); - - ReleaseSysCache(rvTypeTup); - } + PLy_procedure_output_conversion(proc, procStruct); /* * Now get information required for input conversion of the @@ -1482,79 +1573,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) * arguments. */ if (procStruct->pronargs) - { - Oid *types; - char **names, - *modes; - int i, - pos, - total; - - /* extract argument type info from the pg_proc tuple */ - total = get_func_arg_info(procTup, &types, &names, &modes); - - /* count number of in+inout args into proc->nargs */ - if (modes == NULL) - proc->nargs = total; - else - { - /* proc->nargs was initialized to 0 above */ - for (i = 0; i < total; i++) - { - if (modes[i] != PROARGMODE_OUT && - modes[i] != PROARGMODE_TABLE) - (proc->nargs)++; - } - } - - proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs); - for (i = pos = 0; i < total; i++) - { - HeapTuple argTypeTup; - Form_pg_type argTypeStruct; - - if (modes && - (modes[i] == PROARGMODE_OUT || - modes[i] == PROARGMODE_TABLE)) - continue; /* skip OUT arguments */ - - Assert(types[i] == procStruct->proargtypes.values[pos]); - - argTypeTup = SearchSysCache1(TYPEOID, - ObjectIdGetDatum(types[i])); - if (!HeapTupleIsValid(argTypeTup)) - elog(ERROR, "cache lookup failed for type %u", types[i]); - argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup); - - /* check argument type is OK, set up I/O function info */ - switch (argTypeStruct->typtype) - { - case TYPTYPE_PSEUDO: - /* Disallow pseudotype argument */ - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/Python functions cannot accept type %s", - format_type_be(types[i])))); - break; - case TYPTYPE_COMPOSITE: - /* we'll set IO funcs at first call */ - proc->args[pos].is_rowtype = 2; - break; - default: - PLy_input_datum_func(&(proc->args[pos]), - types[i], - argTypeTup); - break; - } - - /* get argument name */ - proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL; - - ReleaseSysCache(argTypeTup); - - pos++; - } - } + PLy_procedure_input_conversion(proc, procTup, procStruct); /* * get the text of the function. -- 2.40.0