Skip to content

Commit 9a633cb

Browse files
committed
Allow planner to fold "stable" functions to constants when forming
selectivity estimates, per recent discussion.
1 parent 8f6278d commit 9a633cb

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
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
* AUTHOR DATE MAJOR EVENT
@@ -76,7 +76,8 @@ static Expr *simplify_function(Oid funcid, Oid result_type, List *args,
7676
bool allow_inline,
7777
eval_const_expressions_context *context);
7878
static Expr *evaluate_function(Oid funcid, Oid result_type, List *args,
79-
HeapTuple func_tuple);
79+
HeapTuple func_tuple,
80+
eval_const_expressions_context *context);
8081
static Expr *inline_function(Oid funcid, Oid result_type, List *args,
8182
HeapTuple func_tuple,
8283
eval_const_expressions_context *context);
@@ -1151,19 +1152,19 @@ eval_const_expressions(Node *node)
11511152
return 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 the only 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 the extra 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
*/
11681169
Node *
11691170
estimate_expression_value(Node *node)
@@ -1909,7 +1910,8 @@ simplify_function(Oid funcid, Oid result_type, List *args,
19091910
if (!HeapTupleIsValid(func_tuple))
19101911
elog(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

19141916
if (!newexpr && allow_inline)
19151917
newexpr = 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
*/
19331936
static Expr *
19341937
evaluate_function(Oid funcid, Oid result_type, List *args,
1935-
HeapTuple func_tuple)
1938+
HeapTuple func_tuple,
1939+
eval_const_expressions_context *context)
19361940
{
19371941
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
19381942
bool has_nonconst_input = false;
@@ -1967,12 +1971,25 @@ evaluate_function(Oid funcid, Oid result_type, List *args,
19671971
return (Expr *) makeNullConst(result_type);
19681972

19691973
/*
1970-
* Otherwise, can simplify only if the 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 if all 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
19761993
return NULL;
19771994

19781995
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy