aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/clauses.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 3da79cc4957..4ed18ee5cd0 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.143 2003/07/01 00:04:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.144 2003/07/01 19:07:02 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -30,6 +30,7 @@
#include "optimizer/var.h"
#include "parser/analyze.h"
#include "parser/parse_clause.h"
+#include "parser/parse_expr.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@@ -1719,6 +1720,8 @@ inline_function(Oid funcid, Oid result_type, List *args,
{
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
char result_typtype;
+ bool polymorphic = false;
+ Oid argtypes[FUNC_MAX_ARGS];
char *src;
Datum tmp;
bool isNull;
@@ -1731,7 +1734,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
int *usecounts;
List *arg;
int i;
- int j;
/*
* Forget it if the function is not SQL-language or has other
@@ -1743,17 +1745,15 @@ inline_function(Oid funcid, Oid result_type, List *args,
funcform->pronargs != length(args))
return NULL;
- /* Forget it if declared return type is not base or domain */
+ /* Forget it if declared return type is not base, domain, or polymorphic */
result_typtype = get_typtype(funcform->prorettype);
if (result_typtype != 'b' &&
result_typtype != 'd')
- return NULL;
-
- /* Forget it if any declared argument type is polymorphic */
- for (j = 0; j < funcform->pronargs; j++)
{
- if (funcform->proargtypes[j] == ANYARRAYOID ||
- funcform->proargtypes[j] == ANYELEMENTOID)
+ if (funcform->prorettype == ANYARRAYOID ||
+ funcform->prorettype == ANYELEMENTOID)
+ polymorphic = true;
+ else
return NULL;
}
@@ -1765,6 +1765,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
return NULL;
+ /* Check for polymorphic arguments, and substitute actual arg types */
+ memcpy(argtypes, funcform->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
+ for (i = 0; i < funcform->pronargs; i++)
+ {
+ if (argtypes[i] == ANYARRAYOID ||
+ argtypes[i] == ANYELEMENTOID)
+ {
+ polymorphic = true;
+ argtypes[i] = exprType((Node *) nth(i, args));
+ }
+ }
+
/*
* Make a temporary memory context, so that we don't leak all the
* stuff that parsing might create.
@@ -1797,8 +1809,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
goto fail;
querytree_list = parse_analyze(lfirst(raw_parsetree_list),
- funcform->proargtypes,
- funcform->pronargs);
+ argtypes, funcform->pronargs);
if (length(querytree_list) != 1)
goto fail;
@@ -1830,6 +1841,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
newexpr = (Node *) ((TargetEntry *) lfirst(querytree->targetList))->expr;
/*
+ * If the function has any arguments declared as polymorphic types,
+ * then it wasn't type-checked at definition time; must do so now.
+ * (This will raise an error if wrong, but that's okay since the
+ * function would fail at runtime anyway. Note we do not try this
+ * until we have verified that no rewriting was needed; that's probably
+ * not important, but let's be careful.)
+ */
+ if (polymorphic)
+ check_sql_fn_retval(result_type, get_typtype(result_type),
+ querytree_list);
+
+ /*
* Additional validity checks on the expression. It mustn't return a
* set, and it mustn't be more volatile than the surrounding function
* (this is to avoid breaking hacks that involve pretending a function