int
get_func_arg_info(HeapTuple procTup,
Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
{
Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
Datum proallargtypes;
Datum proargmodes;
Datum proargnames;
bool isNull;
ArrayType *arr;
int numargs;
Datum *elems;
int nelems;
int i;
proallargtypes = SysCacheGetAttr(PROCOID, procTup,
Anum_pg_proc_proallargtypes,
&isNull);
if (!isNull)
{
arr = DatumGetArrayTypeP(proallargtypes);
numargs = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
numargs < 0 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
memcpy(*p_argtypes, ARR_DATA_PTR(arr),
numargs * sizeof(Oid));
}
else
{
numargs = procStruct->proargtypes.dim1;
*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
memcpy(*p_argtypes, procStruct->proargtypes.values,
numargs * sizeof(Oid));
}
proargnames = SysCacheGetAttr(PROCOID, procTup,
Anum_pg_proc_proargnames,
&isNull);
if (isNull)
*p_argnames = NULL;
else
{
deconstruct_array_builtin(DatumGetArrayTypeP(proargnames), TEXTOID,
&elems, NULL, &nelems);
if (nelems != numargs)
elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
*p_argnames = (char **) palloc(sizeof(char *) * numargs);
for (i = 0; i < numargs; i++)
(*p_argnames)[i] = TextDatumGetCString(elems[i]);
}
proargmodes = SysCacheGetAttr(PROCOID, procTup,
Anum_pg_proc_proargmodes,
&isNull);
if (isNull)
*p_argmodes = NULL;
else
{
arr = DatumGetArrayTypeP(proargmodes);
if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numargs ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != CHAROID)
elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
numargs);
*p_argmodes = (char *) palloc(numargs * sizeof(char));
memcpy(*p_argmodes, ARR_DATA_PTR(arr),
numargs * sizeof(char));
}
return numargs;
}