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) ...@@ -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 * static void
PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) 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; HeapTuple rvTypeTup;
Form_pg_type rvTypeStruct; Form_pg_type rvTypeStruct;
/* Get the return type */
rvTypeTup = SearchSysCache1(TYPEOID, rvTypeTup = SearchSysCache1(TYPEOID,
ObjectIdGetDatum(procStruct->prorettype)); ObjectIdGetDatum(procStruct->prorettype));
if (!HeapTupleIsValid(rvTypeTup)) if (!HeapTupleIsValid(rvTypeTup))
...@@ -1469,20 +1427,21 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -1469,20 +1427,21 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
proc->result.is_rowtype = 2; proc->result.is_rowtype = 2;
} }
else else
{
/* Do the real work */
PLy_output_datum_func(&proc->result, rvTypeTup); PLy_output_datum_func(&proc->result, rvTypeTup);
}
ReleaseSysCache(rvTypeTup); ReleaseSysCache(rvTypeTup);
} }
/* /*
* Now get information required for input conversion of the * Set up output conversion functions for a procedure
* 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) static void
{ PLy_procedure_input_conversion(PLyProcedure *proc, HeapTuple procTup,
Form_pg_proc procStruct)
{
Oid *types; Oid *types;
char **names, char **names,
*modes; *modes;
...@@ -1490,10 +1449,10 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -1490,10 +1449,10 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
pos, pos,
total; 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); 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) if (modes == NULL)
proc->nargs = total; proc->nargs = total;
else else
...@@ -1526,7 +1485,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -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]); elog(ERROR, "cache lookup failed for type %u", types[i]);
argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup); 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) switch (argTypeStruct->typtype)
{ {
case TYPTYPE_PSEUDO: case TYPTYPE_PSEUDO:
...@@ -1537,7 +1496,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -1537,7 +1496,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
format_type_be(types[i])))); format_type_be(types[i]))));
break; break;
case TYPTYPE_COMPOSITE: 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; proc->args[pos].is_rowtype = 2;
break; break;
default: default:
...@@ -1547,14 +1506,74 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) ...@@ -1547,14 +1506,74 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
break; break;
} }
/* get argument name */ /* Get argument name */
proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL; proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
ReleaseSysCache(argTypeTup); ReleaseSysCache(argTypeTup);
pos++; 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. * 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