summaryrefslogtreecommitdiff
path: root/src/backend/catalog/pg_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/pg_proc.c')
-rw-r--r--src/backend/catalog/pg_proc.c72
1 files changed, 67 insertions, 5 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 1f11f82a30..37e7ed4343 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.151 2008/03/27 03:57:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.152 2008/07/16 16:55:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -85,6 +85,7 @@ ProcedureCreate(const char *procedureName,
bool genericOutParam = false;
bool internalInParam = false;
bool internalOutParam = false;
+ Oid variadicType = InvalidOid;
Relation rel;
HeapTuple tup;
HeapTuple oldtup;
@@ -103,7 +104,6 @@ ProcedureCreate(const char *procedureName,
* sanity checks
*/
Assert(PointerIsValid(prosrc));
- Assert(PointerIsValid(probin));
parameterCount = parameterTypes->dim1;
if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
@@ -211,6 +211,64 @@ ProcedureCreate(const char *procedureName,
procedureName,
format_type_be(parameterTypes->values[0]))));
+ if (parameterModes != PointerGetDatum(NULL))
+ {
+ /*
+ * We expect the array to be a 1-D CHAR array; verify that. We don't
+ * need to use deconstruct_array() since the array data is just going
+ * to look like a C array of char values.
+ */
+ ArrayType *modesArray = (ArrayType *) DatumGetPointer(parameterModes);
+ char *modes;
+
+ if (ARR_NDIM(modesArray) != 1 ||
+ ARR_DIMS(modesArray)[0] != allParamCount ||
+ ARR_HASNULL(modesArray) ||
+ ARR_ELEMTYPE(modesArray) != CHAROID)
+ elog(ERROR, "parameterModes is not a 1-D char array");
+ modes = (char *) ARR_DATA_PTR(modesArray);
+ /*
+ * Only the last input parameter can be variadic; if it is, save
+ * its element type. Errors here are just elog since caller should
+ * have checked this already.
+ */
+ for (i = 0; i < allParamCount; i++)
+ {
+ switch (modes[i])
+ {
+ case PROARGMODE_IN:
+ case PROARGMODE_INOUT:
+ if (OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter must be last");
+ break;
+ case PROARGMODE_OUT:
+ /* okay */
+ break;
+ case PROARGMODE_VARIADIC:
+ if (OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter must be last");
+ switch (allParams[i])
+ {
+ case ANYOID:
+ variadicType = ANYOID;
+ break;
+ case ANYARRAYOID:
+ variadicType = ANYELEMENTOID;
+ break;
+ default:
+ variadicType = get_element_type(allParams[i]);
+ if (!OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter is not an array");
+ break;
+ }
+ break;
+ default:
+ elog(ERROR, "invalid parameter mode '%c'", modes[i]);
+ break;
+ }
+ }
+ }
+
/*
* All seems OK; prepare the data to be inserted into pg_proc.
*/
@@ -229,6 +287,7 @@ ProcedureCreate(const char *procedureName,
values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId);
values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost);
values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows);
+ values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType);
values[Anum_pg_proc_proisagg - 1] = BoolGetDatum(isAgg);
values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer);
values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict);
@@ -250,7 +309,10 @@ ProcedureCreate(const char *procedureName,
else
nulls[Anum_pg_proc_proargnames - 1] = 'n';
values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
- values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
+ if (probin)
+ values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
+ else
+ nulls[Anum_pg_proc_probin - 1] = 'n';
if (proconfig != PointerGetDatum(NULL))
values[Anum_pg_proc_proconfig - 1] = proconfig;
else
@@ -497,12 +559,12 @@ fmgr_c_validator(PG_FUNCTION_ARGS)
tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
if (isnull)
- elog(ERROR, "null prosrc");
+ elog(ERROR, "null prosrc for C function %u", funcoid);
prosrc = TextDatumGetCString(tmp);
tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull);
if (isnull)
- elog(ERROR, "null probin");
+ elog(ERROR, "null probin for C function %u", funcoid);
probin = TextDatumGetCString(tmp);
(void) load_external_function(probin, prosrc, true, &libraryhandle);