mirror of
https://github.com/postgres/postgres.git
synced 2025-05-15 19:15:29 +03:00
Factor out functions responsible for caching I/O routines
This makes PLy_procedure_create a bit more manageable. Jan Urbański
This commit is contained in:
parent
9c5e2c120b
commit
740e54ca84
@ -1385,6 +1385,136 @@ PLy_procedure_get(Oid fn_oid, bool is_trigger)
|
|||||||
return entry->proc;
|
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
|
* 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.
|
* but only if this isn't a trigger.
|
||||||
*/
|
*/
|
||||||
if (!is_trigger)
|
if (!is_trigger)
|
||||||
{
|
PLy_procedure_output_conversion(proc, procStruct);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now get information required for input conversion of the
|
* 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.
|
* arguments.
|
||||||
*/
|
*/
|
||||||
if (procStruct->pronargs)
|
if (procStruct->pronargs)
|
||||||
{
|
PLy_procedure_input_conversion(proc, procTup, 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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get the text of the function.
|
* get the text of the function.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user