aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/fmgr/funcapi.c105
-rw-r--r--src/include/funcapi.h10
-rw-r--r--src/pl/plpgsql/src/pl_comp.c104
-rw-r--r--src/pl/plpgsql/src/pl_handler.c33
4 files changed, 131 insertions, 121 deletions
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index b545928d9b9..b450b2ee546 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.27 2005/11/17 22:14:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.28 2005/12/28 18:11:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -629,6 +629,109 @@ get_type_func_class(Oid typid)
/*
+ * get_func_arg_info
+ *
+ * Fetch info about the argument types, names, and IN/OUT modes from the
+ * pg_proc tuple. Return value is the total number of arguments.
+ * Other results are palloc'd. *p_argtypes is always filled in, but
+ * *p_argnames and *p_argmodes will be set NULL in the default cases
+ * (no names, and all IN arguments, respectively).
+ *
+ * Note that this function simply fetches what is in the pg_proc tuple;
+ * it doesn't do any interpretation of polymorphic types.
+ */
+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;
+
+ /* First discover the total number of parameters and get their types */
+ proallargtypes = SysCacheGetAttr(PROCOID, procTup,
+ Anum_pg_proc_proallargtypes,
+ &isNull);
+ if (!isNull)
+ {
+ /*
+ * We expect the arrays to be 1-D arrays of the right types; verify
+ * that. For the OID and char arrays, we don't need to use
+ * deconstruct_array() since the array data is just going to look like
+ * a C array of values.
+ */
+ arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
+ 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");
+ Assert(numargs >= procStruct->pronargs);
+ *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+ memcpy(*p_argtypes, ARR_DATA_PTR(arr),
+ numargs * sizeof(Oid));
+ }
+ else
+ {
+ /* If no proallargtypes, use proargtypes */
+ numargs = procStruct->proargtypes.dim1;
+ Assert(numargs == procStruct->pronargs);
+ *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+ memcpy(*p_argtypes, procStruct->proargtypes.values,
+ numargs * sizeof(Oid));
+ }
+
+ /* Get argument names, if available */
+ proargnames = SysCacheGetAttr(PROCOID, procTup,
+ Anum_pg_proc_proargnames,
+ &isNull);
+ if (isNull)
+ *p_argnames = NULL;
+ else
+ {
+ deconstruct_array(DatumGetArrayTypeP(proargnames),
+ TEXTOID, -1, false, 'i',
+ &elems, NULL, &nelems);
+ if (nelems != numargs) /* should not happen */
+ 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] = DatumGetCString(DirectFunctionCall1(textout,
+ elems[i]));
+ }
+
+ /* Get argument modes, if available */
+ proargmodes = SysCacheGetAttr(PROCOID, procTup,
+ Anum_pg_proc_proargmodes,
+ &isNull);
+ if (isNull)
+ *p_argmodes = NULL;
+ else
+ {
+ arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
+ 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");
+ *p_argmodes = (char *) palloc(numargs * sizeof(char));
+ memcpy(*p_argmodes, ARR_DATA_PTR(arr),
+ numargs * sizeof(char));
+ }
+
+ return numargs;
+}
+
+
+/*
* get_func_result_name
*
* If the function has exactly one output parameter, and that parameter
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index 1f455d3eeaf..ccc61dfbf08 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -9,7 +9,7 @@
*
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.21 2005/11/22 18:17:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.22 2005/12/28 18:11:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -165,12 +165,16 @@ extern TypeFuncClass get_func_result_type(Oid functionId,
Oid *resultTypeId,
TupleDesc *resultTupleDesc);
-extern char *get_func_result_name(Oid functionId);
-
extern bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes,
char *argmodes,
Node *call_expr);
+extern int get_func_arg_info(HeapTuple procTup,
+ Oid **p_argtypes, char ***p_argnames,
+ char **p_argmodes);
+
+extern char *get_func_result_name(Oid functionId);
+
extern TupleDesc build_function_result_tupdesc_d(Datum proallargtypes,
Datum proargmodes,
Datum proargnames);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index b89f975981c..d9fa1f0e422 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.97 2005/12/09 17:08:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.98 2005/12/28 18:11:25 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -123,9 +123,6 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
HeapTuple procTup,
PLpgSQL_func_hashkey *hashkey,
bool forValidator);
-static int fetchArgInfo(HeapTuple procTup,
- Oid **p_argtypes, char ***p_argnames,
- char **p_argmodes);
static PLpgSQL_row *build_row_from_class(Oid classOid);
static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
@@ -358,7 +355,8 @@ do_compile(FunctionCallInfo fcinfo,
*/
MemoryContextSwitchTo(compile_tmp_cxt);
- numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
+ numargs = get_func_arg_info(procTup,
+ &argtypes, &argnames, &argmodes);
plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
fcinfo->flinfo->fn_expr,
@@ -751,102 +749,6 @@ plpgsql_compile_error_callback(void *arg)
}
-/*
- * Fetch info about the argument types, names, and IN/OUT modes from the
- * pg_proc tuple. Return value is the number of arguments.
- * Other results are palloc'd.
- */
-static int
-fetchArgInfo(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;
-
- /* First discover the total number of parameters and get their types */
- proallargtypes = SysCacheGetAttr(PROCOID, procTup,
- Anum_pg_proc_proallargtypes,
- &isNull);
- if (!isNull)
- {
- /*
- * We expect the arrays to be 1-D arrays of the right types; verify
- * that. For the OID and char arrays, we don't need to use
- * deconstruct_array() since the array data is just going to look like
- * a C array of values.
- */
- arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
- 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");
- Assert(numargs >= procStruct->pronargs);
- *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
- memcpy(*p_argtypes, ARR_DATA_PTR(arr),
- numargs * sizeof(Oid));
- }
- else
- {
- /* If no proallargtypes, use proargtypes */
- numargs = procStruct->proargtypes.dim1;
- Assert(numargs == procStruct->pronargs);
- *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
- memcpy(*p_argtypes, procStruct->proargtypes.values,
- numargs * sizeof(Oid));
- }
-
- /* Get argument names, if available */
- proargnames = SysCacheGetAttr(PROCOID, procTup,
- Anum_pg_proc_proargnames,
- &isNull);
- if (isNull)
- *p_argnames = NULL;
- else
- {
- deconstruct_array(DatumGetArrayTypeP(proargnames),
- TEXTOID, -1, false, 'i',
- &elems, NULL, &nelems);
- if (nelems != numargs) /* should not happen */
- 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] = DatumGetCString(DirectFunctionCall1(textout,
- elems[i]));
- }
-
- /* Get argument modes, if available */
- proargmodes = SysCacheGetAttr(PROCOID, procTup,
- Anum_pg_proc_proargmodes,
- &isNull);
- if (isNull)
- *p_argmodes = NULL;
- else
- {
- arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
- 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");
- *p_argmodes = (char *) palloc(numargs * sizeof(char));
- memcpy(*p_argmodes, ARR_DATA_PTR(arr),
- numargs * sizeof(char));
- }
-
- return numargs;
-}
-
-
/* ----------
* plpgsql_parse_word The scanner calls this to postparse
* any single word not found by a
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 69d128e8698..59e6acc7893 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.26 2005/10/15 02:49:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.27 2005/12/28 18:11:25 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -41,6 +41,7 @@
#include "access/heapam.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "funcapi.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -147,9 +148,11 @@ plpgsql_validator(PG_FUNCTION_ARGS)
HeapTuple tuple;
Form_pg_proc proc;
char functyptype;
+ int numargs;
+ Oid *argtypes;
+ char **argnames;
+ char *argmodes;
bool istrigger = false;
- bool haspolyresult;
- bool haspolyarg;
int i;
/* perform initialization */
@@ -173,32 +176,30 @@ plpgsql_validator(PG_FUNCTION_ARGS)
if (proc->prorettype == TRIGGEROID ||
(proc->prorettype == OPAQUEOID && proc->pronargs == 0))
istrigger = true;
- else if (proc->prorettype == ANYARRAYOID ||
- proc->prorettype == ANYELEMENTOID)
- haspolyresult = true;
else if (proc->prorettype != RECORDOID &&
- proc->prorettype != VOIDOID)
+ proc->prorettype != VOIDOID &&
+ proc->prorettype != ANYARRAYOID &&
+ proc->prorettype != ANYELEMENTOID)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("plpgsql functions cannot return type %s",
format_type_be(proc->prorettype))));
}
- /* Disallow pseudotypes in arguments */
+ /* Disallow pseudotypes in arguments (either IN or OUT) */
/* except for ANYARRAY or ANYELEMENT */
- haspolyarg = false;
- for (i = 0; i < proc->pronargs; i++)
+ numargs = get_func_arg_info(tuple,
+ &argtypes, &argnames, &argmodes);
+ for (i = 0; i < numargs; i++)
{
- if (get_typtype(proc->proargtypes.values[i]) == 'p')
+ if (get_typtype(argtypes[i]) == 'p')
{
- if (proc->proargtypes.values[i] == ANYARRAYOID ||
- proc->proargtypes.values[i] == ANYELEMENTOID)
- haspolyarg = true;
- else
+ if (argtypes[i] != ANYARRAYOID &&
+ argtypes[i] != ANYELEMENTOID)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("plpgsql functions cannot take type %s",
- format_type_be(proc->proargtypes.values[i]))));
+ format_type_be(argtypes[i]))));
}
}