/**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL
*
- * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.108 2008/03/28 00:21:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.109 2008/05/03 02:47:47 tgl Exp $
*
*********************************************************************
*/
bool isnull;
int i,
rv;
- Datum argnames;
- Datum *elems;
- int nelems;
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
}
/*
- * now get information required for input conversion of the
- * procedure's arguments.
+ * Now get information required for input conversion of the
+ * procedure's arguments. Note that we ignore output arguments
+ * here --- since we don't support returning record, and that was
+ * already checked above, there's no need to worry about multiple
+ * output arguments.
*/
- proc->nargs = procStruct->pronargs;
- if (proc->nargs)
+ if (procStruct->pronargs)
{
- argnames = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames, &isnull);
- if (!isnull)
+ 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
{
- /* XXX this code is WRONG if there are any output arguments */
- deconstruct_array(DatumGetArrayTypeP(argnames), TEXTOID, -1, false, 'i',
- &elems, NULL, &nelems);
- if (nelems != proc->nargs)
- elog(ERROR,
- "proargnames must have the same number of elements "
- "as the function has arguments");
- proc->argnames = (char **) PLy_malloc(sizeof(char *) * proc->nargs);
- memset(proc->argnames, 0, sizeof(char *) * proc->nargs);
+ /* proc->nargs was initialized to 0 above */
+ for (i = 0; i < total; i++)
+ {
+ if (modes[i] != 'o')
+ (proc->nargs)++;
+ }
}
- }
- for (i = 0; i < proc->nargs; i++)
- {
- HeapTuple argTypeTup;
- Form_pg_type argTypeStruct;
- argTypeTup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(procStruct->proargtypes.values[i]),
- 0, 0, 0);
- if (!HeapTupleIsValid(argTypeTup))
- elog(ERROR, "cache lookup failed for type %u",
- procStruct->proargtypes.values[i]);
- argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
+ proc->argnames = (char **) PLy_malloc(sizeof(char *) * proc->nargs);
+ for (i = pos = 0; i < total; i++)
+ {
+ HeapTuple argTypeTup;
+ Form_pg_type argTypeStruct;
- /* Disallow pseudotype argument */
- if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("plpython functions cannot take type %s",
- format_type_be(procStruct->proargtypes.values[i]))));
-
- if (argTypeStruct->typtype != TYPTYPE_COMPOSITE)
- PLy_input_datum_func(&(proc->args[i]),
- procStruct->proargtypes.values[i],
- argTypeTup);
- else
- proc->args[i].is_rowtype = 2; /* still need to set I/O funcs */
+ if (modes && modes[i] == 'o') /* skip OUT arguments */
+ continue;
+
+ Assert(types[i] == procStruct->proargtypes.values[pos]);
+
+ argTypeTup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(types[i]),
+ 0, 0, 0);
+ 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("plpython functions cannot take 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;
+ }
- ReleaseSysCache(argTypeTup);
+ /* get argument name */
+ proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
- /* Fetch argument name */
- if (proc->argnames)
- proc->argnames[i] = PLy_strdup(TextDatumGetCString(elems[i]));
+ ReleaseSysCache(argTypeTup);
+
+ pos++;
+ }
}
/*