88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.183 2004/10/22 17:20:05 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.184 2004/11/09 21:42:53 tgl Exp $
1212 *
1313 * HISTORY
1414 * AUTHORDATEMAJOR EVENT
@@ -76,7 +76,8 @@ static Expr *simplify_function(Oid funcid, Oid result_type, List *args,
7676bool allow_inline ,
7777eval_const_expressions_context * context );
7878static Expr * evaluate_function (Oid funcid ,Oid result_type ,List * args ,
79- HeapTuple func_tuple );
79+ HeapTuple func_tuple ,
80+ eval_const_expressions_context * context );
8081static Expr * inline_function (Oid funcid ,Oid result_type ,List * args ,
8182HeapTuple func_tuple ,
8283eval_const_expressions_context * context );
@@ -1151,19 +1152,19 @@ eval_const_expressions(Node *node)
11511152return eval_const_expressions_mutator (node ,& context );
11521153}
11531154
1154- /*
1155+ /*--------------------
11551156 * estimate_expression_value
11561157 *
11571158 * This function attempts to estimate the value of an expression for
11581159 * planning purposes. It is in essence a more aggressive version of
11591160 * eval_const_expressions(): we will perform constant reductions that are
11601161 * not necessarily 100% safe, but are reasonable for estimation purposes.
11611162 *
1162- * Currently theonly such transform is to substitute values for Params,
1163- *when a bound Param value has been made available by the caller of planner().
1164- *In future we might consider other things, such as reducing now() to current
1165- *time. (XXX seems like there could be a lot of scope for ideas here.. .
1166- * but we might need more volatility classifications ...)
1163+ * Currently theextra steps that are taken in this mode are:
1164+ *1. Substitute values for Params, where a bound Param value has been made
1165+ * available by the caller of planner().
1166+ *2. Fold stable, as well as immutable, functions to constants .
1167+ *--------------------
11671168 */
11681169Node *
11691170estimate_expression_value (Node * node )
@@ -1909,7 +1910,8 @@ simplify_function(Oid funcid, Oid result_type, List *args,
19091910if (!HeapTupleIsValid (func_tuple ))
19101911elog (ERROR ,"cache lookup failed for function %u" ,funcid );
19111912
1912- newexpr = evaluate_function (funcid ,result_type ,args ,func_tuple );
1913+ newexpr = evaluate_function (funcid ,result_type ,args ,
1914+ func_tuple ,context );
19131915
19141916if (!newexpr && allow_inline )
19151917newexpr = inline_function (funcid ,result_type ,args ,
@@ -1925,14 +1927,16 @@ simplify_function(Oid funcid, Oid result_type, List *args,
19251927 *
19261928 * We can do this if the function is strict and has any constant-null inputs
19271929 * (just return a null constant), or if the function is immutable and has all
1928- * constant inputs (call it and return the result as a Const node).
1930+ * constant inputs (call it and return the result as a Const node). In
1931+ * estimation mode we are willing to pre-evaluate stable functions too.
19291932 *
19301933 * Returns a simplified expression if successful, or NULL if cannot
19311934 * simplify the function.
19321935 */
19331936static Expr *
19341937evaluate_function (Oid funcid ,Oid result_type ,List * args ,
1935- HeapTuple func_tuple )
1938+ HeapTuple func_tuple ,
1939+ eval_const_expressions_context * context )
19361940{
19371941Form_pg_proc funcform = (Form_pg_proc )GETSTRUCT (func_tuple );
19381942bool has_nonconst_input = false;
@@ -1967,12 +1971,25 @@ evaluate_function(Oid funcid, Oid result_type, List *args,
19671971return (Expr * )makeNullConst (result_type );
19681972
19691973/*
1970- * Otherwise, can simplify only ifthe function is immutable and all
1971- *inputs are constants. (For a non-strict function, constant NULL
1972- *inputs are treated the same as constant non-NULL inputs.)
1974+ * Otherwise, can simplify only ifall inputs are constants. (For a
1975+ * non-strict function, constant NULL inputs are treated the same as
1976+ * constant non-NULL inputs.)
19731977 */
1974- if (funcform -> provolatile != PROVOLATILE_IMMUTABLE ||
1975- has_nonconst_input )
1978+ if (has_nonconst_input )
1979+ return NULL ;
1980+
1981+ /*
1982+ * Ordinarily we are only allowed to simplify immutable functions.
1983+ * But for purposes of estimation, we consider it okay to simplify
1984+ * functions that are merely stable; the risk that the result might
1985+ * change from planning time to execution time is worth taking in
1986+ * preference to not being able to estimate the value at all.
1987+ */
1988+ if (funcform -> provolatile == PROVOLATILE_IMMUTABLE )
1989+ /* okay */ ;
1990+ else if (context -> estimate && funcform -> provolatile == PROVOLATILE_STABLE )
1991+ /* okay */ ;
1992+ else
19761993return NULL ;
19771994
19781995/*