Skip to content

Commit

Permalink
Allow use of OUT parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
jconway committed Mar 31, 2013
1 parent 917d0b9 commit 5d4d925
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 41 deletions.
117 changes: 76 additions & 41 deletions plr.c
Expand Up @@ -177,10 +177,13 @@ static void plr_error_callback(void *arg);
static Oid getNamespaceOidFromFunctionOid(Oid fnOid);
static bool haveModulesTable(Oid nspOid);
static char *getModulesSql(Oid nspOid);
static char **fetchArgNames(HeapTuple procTup, int nargs);
#ifdef HAVE_WINDOW_FUNCTIONS
static void WinGetFrameData(WindowObject winobj, int argno, Datum *dvalues, bool *isnull, int *numels, bool *has_nulls);
#endif
static void plr_resolve_polymorphic_argtypes(int numargs,
Oid *argtypes, char *argmodes,
Node *call_expr, bool forValidator,
const char *proname);

/*
* plr_call_handler - This is the only visible function
Expand Down Expand Up @@ -1136,11 +1139,31 @@ do_compile(FunctionCallInfo fcinfo,
if (!is_trigger)
{
int i;
GET_ARG_NAMES;
bool forValidator = false;
int numargs;
Oid *argtypes;
char **argnames;
char *argmodes;

numargs = get_func_arg_info(procTup,
&argtypes, &argnames, &argmodes);

plr_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
fcinfo->flinfo->fn_expr,
forValidator,
function->proname);


function->nargs = procStruct->pronargs;
for (i = 0; i < function->nargs; i++)
{
char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;

if (argmode != PROARGMODE_IN &&
argmode != PROARGMODE_INOUT &&
argmode != PROARGMODE_VARIADIC)
continue;

/*
* Since we already did the replacement of polymorphic
* argument types by actual argument types while computing
Expand Down Expand Up @@ -1653,45 +1676,6 @@ plr_error_callback(void *arg)
errcontext("In PL/R function %s", (char *) arg);
}

/*
* Fetch the argument names, if any, from the proargnames field of the
* pg_proc tuple. Results are palloc'd.
*
* Borrowed from src/pl/plpgsql/src/pl_comp.c
*/
static char **
fetchArgNames(HeapTuple procTup, int nargs)
{
Datum argnamesDatum;
bool isNull;
Datum *elems;
int nelems;
char **result;
int i;

if (nargs == 0)
return NULL;

argnamesDatum = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames,
&isNull);
if (isNull)
return NULL;

deconstruct_array(DatumGetArrayTypeP(argnamesDatum),
TEXTOID, -1, false, 'i',
&elems, NULL, &nelems);

if (nelems != nargs) /* should not happen */
elog(ERROR, "proargnames must have the same number of elements as the function has arguments");

result = (char **) palloc(sizeof(char *) * nargs);

for (i=0; i < nargs; i++)
result[i] = DatumGetCString(DirectFunctionCall1(textout, elems[i]));

return result;
}

/*
* getNamespaceOidFromFunctionOid - Returns the OID of the namespace for the
* language handler function for the postgresql function with the OID equal
Expand Down Expand Up @@ -1854,3 +1838,54 @@ WinGetFrameData(WindowObject winobj, int argno, Datum *dvalues, bool *isnulls, i
}
#endif

/*
* swiped out of plpgsql pl_comp.c
*
* This is the same as the standard resolve_polymorphic_argtypes() function,
* but with a special case for validation: assume that polymorphic arguments
* are integer, integer-array or integer-range. Also, we go ahead and report
* the error if we can't resolve the types.
*/
static void
plr_resolve_polymorphic_argtypes(int numargs,
Oid *argtypes, char *argmodes,
Node *call_expr, bool forValidator,
const char *proname)
{
int i;

if (!forValidator)
{
/* normal case, pass to standard routine */
if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
call_expr))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual argument "
"type for polymorphic function \"%s\"",
proname)));
}
else
{
/* special validation case */
for (i = 0; i < numargs; i++)
{
switch (argtypes[i])
{
case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: /* XXX dubious */
argtypes[i] = INT4OID;
break;
case ANYARRAYOID:
argtypes[i] = INT4ARRAYOID;
break;
case ANYRANGEOID:
argtypes[i] = INT4RANGEOID;
break;
default:
break;
}
}
}
}
5 changes: 5 additions & 0 deletions plr.h
Expand Up @@ -44,6 +44,11 @@
#include "windowapi.h"
#endif
#include "access/heapam.h"
#if PG_VERSION_NUM >= 90300
#include "access/htup_details.h"
#else
#include "access/htup.h"
#endif
#include "catalog/catversion.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
Expand Down

0 comments on commit 5d4d925

Please sign in to comment.