Commit 740e54ca authored by Peter Eisentraut's avatar Peter Eisentraut

Factor out functions responsible for caching I/O routines

This makes PLy_procedure_create a bit more manageable.

Jan Urbański
parent 9c5e2c12
......@@ -1386,57 +1386,15 @@ PLy_procedure_get(Oid fn_oid, bool is_trigger)
}
/*
* Create a new PLyProcedure structure
* Set up output conversion functions for a procedure
*/
static PLyProcedure *
PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
static void
PLy_procedure_output_conversion(PLyProcedure *proc, Form_pg_proc procStruct)
{
char procName[NAMEDATALEN + 256];
Form_pg_proc procStruct;
PLyProcedure *volatile proc;
char *volatile procSource = NULL;
Datum prosrcdatum;
bool isnull;
int i,
rv;
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
rv = snprintf(procName, sizeof(procName),
"__plpython_procedure_%s_%u",
NameStr(procStruct->proname),
fn_oid);
if (rv >= sizeof(procName) || rv < 0)
elog(ERROR, "procedure name would overrun buffer");
proc = PLy_malloc(sizeof(PLyProcedure));
proc->proname = PLy_strdup(NameStr(procStruct->proname));
proc->pyname = PLy_strdup(procName);
proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
proc->fn_tid = procTup->t_self;
/* Remember if function is STABLE/IMMUTABLE */
proc->fn_readonly =
(procStruct->provolatile != PROVOLATILE_VOLATILE);
PLy_typeinfo_init(&proc->result);
for (i = 0; i < FUNC_MAX_ARGS; i++)
PLy_typeinfo_init(&proc->args[i]);
proc->nargs = 0;
proc->code = proc->statics = NULL;
proc->globals = NULL;
proc->is_setof = procStruct->proretset;
proc->setof = NULL;
proc->argnames = NULL;
PG_TRY();
{
/*
* get information required for output conversion of the return value,
* but only if this isn't a trigger.
*/
if (!is_trigger)
{
HeapTuple rvTypeTup;
Form_pg_type rvTypeStruct;
/* Get the return type */
rvTypeTup = SearchSysCache1(TYPEOID,
ObjectIdGetDatum(procStruct->prorettype));
if (!HeapTupleIsValid(rvTypeTup))
......@@ -1469,20 +1427,21 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
proc->result.is_rowtype = 2;
}
else
{
/* Do the real work */
PLy_output_datum_func(&proc->result, rvTypeTup);
}
ReleaseSysCache(rvTypeTup);
}
}
/*
* 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.
/*
* Set up output conversion functions for a procedure
*/
if (procStruct->pronargs)
{
static void
PLy_procedure_input_conversion(PLyProcedure *proc, HeapTuple procTup,
Form_pg_proc procStruct)
{
Oid *types;
char **names,
*modes;
......@@ -1490,10 +1449,10 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
pos,
total;
/* extract argument type info from the pg_proc tuple */
/* 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 */
/* Count number of in+inout args into proc->nargs */
if (modes == NULL)
proc->nargs = total;
else
......@@ -1526,7 +1485,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
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 */
/* Check argument type is OK, set up I/O function info */
switch (argTypeStruct->typtype)
{
case TYPTYPE_PSEUDO:
......@@ -1537,7 +1496,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
format_type_be(types[i]))));
break;
case TYPTYPE_COMPOSITE:
/* we'll set IO funcs at first call */
/* We'll set IO funcs at first call */
proc->args[pos].is_rowtype = 2;
break;
default:
......@@ -1547,14 +1506,74 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
break;
}
/* get argument name */
/* Get argument name */
proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
ReleaseSysCache(argTypeTup);
pos++;
}
}
}
/*
* Create a new PLyProcedure structure
*/
static PLyProcedure *
PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
{
char procName[NAMEDATALEN + 256];
Form_pg_proc procStruct;
PLyProcedure *volatile proc;
char *volatile procSource = NULL;
Datum prosrcdatum;
bool isnull;
int i,
rv;
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
rv = snprintf(procName, sizeof(procName),
"__plpython_procedure_%s_%u",
NameStr(procStruct->proname),
fn_oid);
if (rv >= sizeof(procName) || rv < 0)
elog(ERROR, "procedure name would overrun buffer");
proc = PLy_malloc(sizeof(PLyProcedure));
proc->proname = PLy_strdup(NameStr(procStruct->proname));
proc->pyname = PLy_strdup(procName);
proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
proc->fn_tid = procTup->t_self;
/* Remember if function is STABLE/IMMUTABLE */
proc->fn_readonly =
(procStruct->provolatile != PROVOLATILE_VOLATILE);
PLy_typeinfo_init(&proc->result);
for (i = 0; i < FUNC_MAX_ARGS; i++)
PLy_typeinfo_init(&proc->args[i]);
proc->nargs = 0;
proc->code = proc->statics = NULL;
proc->globals = NULL;
proc->is_setof = procStruct->proretset;
proc->setof = NULL;
proc->argnames = NULL;
PG_TRY();
{
/*
* get information required for output conversion of the return value,
* but only if this isn't a trigger.
*/
if (!is_trigger)
PLy_procedure_output_conversion(proc, procStruct);
/*
* 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.
*/
if (procStruct->pronargs)
PLy_procedure_input_conversion(proc, procTup, procStruct);
/*
* get the text of the function.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment