88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.143 2003/07/0100:04:37 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.144 2003/07/0119:07:02 tgl Exp $
1212 *
1313 * HISTORY
1414 * AUTHORDATEMAJOR EVENT
3030#include "optimizer/var.h"
3131#include "parser/analyze.h"
3232#include "parser/parse_clause.h"
33+ #include "parser/parse_expr.h"
3334#include "tcop/tcopprot.h"
3435#include "utils/acl.h"
3536#include "utils/builtins.h"
@@ -1719,6 +1720,8 @@ inline_function(Oid funcid, Oid result_type, List *args,
17191720{
17201721Form_pg_proc funcform = (Form_pg_proc )GETSTRUCT (func_tuple );
17211722char result_typtype ;
1723+ bool polymorphic = false;
1724+ Oid argtypes [FUNC_MAX_ARGS ];
17221725char * src ;
17231726Datum tmp ;
17241727bool isNull ;
@@ -1731,7 +1734,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
17311734int * usecounts ;
17321735List * arg ;
17331736int i ;
1734- int j ;
17351737
17361738/*
17371739 * 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,
17431745funcform -> pronargs != length (args ))
17441746return NULL ;
17451747
1746- /* Forget it if declared return type is not base ordomain */
1748+ /* Forget it if declared return type is not base, domain, orpolymorphic */
17471749result_typtype = get_typtype (funcform -> prorettype );
17481750if (result_typtype != 'b' &&
17491751result_typtype != 'd' )
1750- return NULL ;
1751-
1752- /* Forget it if any declared argument type is polymorphic */
1753- for (j = 0 ;j < funcform -> pronargs ;j ++ )
17541752{
1755- if (funcform -> proargtypes [j ]== ANYARRAYOID ||
1756- funcform -> proargtypes [j ]== ANYELEMENTOID )
1753+ if (funcform -> prorettype == ANYARRAYOID ||
1754+ funcform -> prorettype == ANYELEMENTOID )
1755+ polymorphic = true;
1756+ else
17571757return NULL ;
17581758}
17591759
@@ -1765,6 +1765,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
17651765if (pg_proc_aclcheck (funcid ,GetUserId (),ACL_EXECUTE )!= ACLCHECK_OK )
17661766return NULL ;
17671767
1768+ /* Check for polymorphic arguments, and substitute actual arg types */
1769+ memcpy (argtypes ,funcform -> proargtypes ,FUNC_MAX_ARGS * sizeof (Oid ));
1770+ for (i = 0 ;i < funcform -> pronargs ;i ++ )
1771+ {
1772+ if (argtypes [i ]== ANYARRAYOID ||
1773+ argtypes [i ]== ANYELEMENTOID )
1774+ {
1775+ polymorphic = true;
1776+ argtypes [i ]= exprType ((Node * )nth (i ,args ));
1777+ }
1778+ }
1779+
17681780/*
17691781 * Make a temporary memory context, so that we don't leak all the
17701782 * stuff that parsing might create.
@@ -1797,8 +1809,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
17971809gotofail ;
17981810
17991811querytree_list = parse_analyze (lfirst (raw_parsetree_list ),
1800- funcform -> proargtypes ,
1801- funcform -> pronargs );
1812+ argtypes ,funcform -> pronargs );
18021813
18031814if (length (querytree_list )!= 1 )
18041815gotofail ;
@@ -1829,6 +1840,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
18291840
18301841newexpr = (Node * ) ((TargetEntry * )lfirst (querytree -> targetList ))-> expr ;
18311842
1843+ /*
1844+ * If the function has any arguments declared as polymorphic types,
1845+ * then it wasn't type-checked at definition time; must do so now.
1846+ * (This will raise an error if wrong, but that's okay since the
1847+ * function would fail at runtime anyway. Note we do not try this
1848+ * until we have verified that no rewriting was needed; that's probably
1849+ * not important, but let's be careful.)
1850+ */
1851+ if (polymorphic )
1852+ check_sql_fn_retval (result_type ,get_typtype (result_type ),
1853+ querytree_list );
1854+
18321855/*
18331856 * Additional validity checks on the expression. It mustn't return a
18341857 * set, and it mustn't be more volatile than the surrounding function