mirror of
https://github.com/postgres/postgres.git
synced 2025-05-22 00:02:02 -04:00
Allow planner to fold "stable" functions to constants when forming
selectivity estimates, per recent discussion.
This commit is contained in:
parent
8f6278d907
commit
9a633cbb6c
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.183 2004/10/22 17:20:05 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.184 2004/11/09 21:42:53 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -76,7 +76,8 @@ static Expr *simplify_function(Oid funcid, Oid result_type, List *args,
|
|||||||
bool allow_inline,
|
bool allow_inline,
|
||||||
eval_const_expressions_context *context);
|
eval_const_expressions_context *context);
|
||||||
static Expr *evaluate_function(Oid funcid, Oid result_type, List *args,
|
static Expr *evaluate_function(Oid funcid, Oid result_type, List *args,
|
||||||
HeapTuple func_tuple);
|
HeapTuple func_tuple,
|
||||||
|
eval_const_expressions_context *context);
|
||||||
static Expr *inline_function(Oid funcid, Oid result_type, List *args,
|
static Expr *inline_function(Oid funcid, Oid result_type, List *args,
|
||||||
HeapTuple func_tuple,
|
HeapTuple func_tuple,
|
||||||
eval_const_expressions_context *context);
|
eval_const_expressions_context *context);
|
||||||
@ -1151,7 +1152,7 @@ eval_const_expressions(Node *node)
|
|||||||
return eval_const_expressions_mutator(node, &context);
|
return eval_const_expressions_mutator(node, &context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*--------------------
|
||||||
* estimate_expression_value
|
* estimate_expression_value
|
||||||
*
|
*
|
||||||
* This function attempts to estimate the value of an expression for
|
* This function attempts to estimate the value of an expression for
|
||||||
@ -1159,11 +1160,11 @@ eval_const_expressions(Node *node)
|
|||||||
* eval_const_expressions(): we will perform constant reductions that are
|
* eval_const_expressions(): we will perform constant reductions that are
|
||||||
* not necessarily 100% safe, but are reasonable for estimation purposes.
|
* not necessarily 100% safe, but are reasonable for estimation purposes.
|
||||||
*
|
*
|
||||||
* Currently the only such transform is to substitute values for Params,
|
* Currently the extra steps that are taken in this mode are:
|
||||||
* when a bound Param value has been made available by the caller of planner().
|
* 1. Substitute values for Params, where a bound Param value has been made
|
||||||
* In future we might consider other things, such as reducing now() to current
|
* available by the caller of planner().
|
||||||
* time. (XXX seems like there could be a lot of scope for ideas here...
|
* 2. Fold stable, as well as immutable, functions to constants.
|
||||||
* but we might need more volatility classifications ...)
|
*--------------------
|
||||||
*/
|
*/
|
||||||
Node *
|
Node *
|
||||||
estimate_expression_value(Node *node)
|
estimate_expression_value(Node *node)
|
||||||
@ -1909,7 +1910,8 @@ simplify_function(Oid funcid, Oid result_type, List *args,
|
|||||||
if (!HeapTupleIsValid(func_tuple))
|
if (!HeapTupleIsValid(func_tuple))
|
||||||
elog(ERROR, "cache lookup failed for function %u", funcid);
|
elog(ERROR, "cache lookup failed for function %u", funcid);
|
||||||
|
|
||||||
newexpr = evaluate_function(funcid, result_type, args, func_tuple);
|
newexpr = evaluate_function(funcid, result_type, args,
|
||||||
|
func_tuple, context);
|
||||||
|
|
||||||
if (!newexpr && allow_inline)
|
if (!newexpr && allow_inline)
|
||||||
newexpr = inline_function(funcid, result_type, args,
|
newexpr = inline_function(funcid, result_type, args,
|
||||||
@ -1925,14 +1927,16 @@ simplify_function(Oid funcid, Oid result_type, List *args,
|
|||||||
*
|
*
|
||||||
* We can do this if the function is strict and has any constant-null inputs
|
* We can do this if the function is strict and has any constant-null inputs
|
||||||
* (just return a null constant), or if the function is immutable and has all
|
* (just return a null constant), or if the function is immutable and has all
|
||||||
* constant inputs (call it and return the result as a Const node).
|
* constant inputs (call it and return the result as a Const node). In
|
||||||
|
* estimation mode we are willing to pre-evaluate stable functions too.
|
||||||
*
|
*
|
||||||
* Returns a simplified expression if successful, or NULL if cannot
|
* Returns a simplified expression if successful, or NULL if cannot
|
||||||
* simplify the function.
|
* simplify the function.
|
||||||
*/
|
*/
|
||||||
static Expr *
|
static Expr *
|
||||||
evaluate_function(Oid funcid, Oid result_type, List *args,
|
evaluate_function(Oid funcid, Oid result_type, List *args,
|
||||||
HeapTuple func_tuple)
|
HeapTuple func_tuple,
|
||||||
|
eval_const_expressions_context *context)
|
||||||
{
|
{
|
||||||
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
|
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
|
||||||
bool has_nonconst_input = false;
|
bool has_nonconst_input = false;
|
||||||
@ -1967,12 +1971,25 @@ evaluate_function(Oid funcid, Oid result_type, List *args,
|
|||||||
return (Expr *) makeNullConst(result_type);
|
return (Expr *) makeNullConst(result_type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, can simplify only if the function is immutable and all
|
* Otherwise, can simplify only if all inputs are constants. (For a
|
||||||
* inputs are constants. (For a non-strict function, constant NULL
|
* non-strict function, constant NULL inputs are treated the same as
|
||||||
* inputs are treated the same as constant non-NULL inputs.)
|
* constant non-NULL inputs.)
|
||||||
*/
|
*/
|
||||||
if (funcform->provolatile != PROVOLATILE_IMMUTABLE ||
|
if (has_nonconst_input)
|
||||||
has_nonconst_input)
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ordinarily we are only allowed to simplify immutable functions.
|
||||||
|
* But for purposes of estimation, we consider it okay to simplify
|
||||||
|
* functions that are merely stable; the risk that the result might
|
||||||
|
* change from planning time to execution time is worth taking in
|
||||||
|
* preference to not being able to estimate the value at all.
|
||||||
|
*/
|
||||||
|
if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
|
||||||
|
/* okay */ ;
|
||||||
|
else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
|
||||||
|
/* okay */ ;
|
||||||
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user