mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Do ScalarArrayOp estimation correctly when array is a stable expression.
Most estimation functions apply estimate_expression_value to see if they can reduce an expression to a constant; the key difference is that it allows evaluation of stable as well as immutable functions in hopes of ending up with a simple Const node. scalararraysel didn't get the memo though, and neither did gincost_opexpr/gincost_scalararrayopexpr. Fix that, and remove a now-unnecessary estimate_expression_value step in the subsidiary function scalararraysel_containment. Per complaint from Alexey Klyukin. Back-patch to 9.3. The problem goes back further, but I'm hesitant to change estimation behavior in long-stable release branches.
This commit is contained in:
@ -1735,6 +1735,10 @@ scalararraysel(PlannerInfo *root,
|
||||
leftop = (Node *) linitial(clause->args);
|
||||
rightop = (Node *) lsecond(clause->args);
|
||||
|
||||
/* aggressively reduce both sides to constants */
|
||||
leftop = estimate_expression_value(root, leftop);
|
||||
rightop = estimate_expression_value(root, rightop);
|
||||
|
||||
/* get nominal (after relabeling) element type of rightop */
|
||||
nominal_element_type = get_base_element_type(exprType(rightop));
|
||||
if (!OidIsValid(nominal_element_type))
|
||||
@ -6856,7 +6860,8 @@ gincost_pattern(IndexOptInfo *index, int indexcol,
|
||||
* appropriately. If the query is unsatisfiable, return false.
|
||||
*/
|
||||
static bool
|
||||
gincost_opexpr(IndexOptInfo *index, OpExpr *clause, GinQualCounts *counts)
|
||||
gincost_opexpr(PlannerInfo *root, IndexOptInfo *index, OpExpr *clause,
|
||||
GinQualCounts *counts)
|
||||
{
|
||||
Node *leftop = get_leftop((Expr *) clause);
|
||||
Node *rightop = get_rightop((Expr *) clause);
|
||||
@ -6880,6 +6885,9 @@ gincost_opexpr(IndexOptInfo *index, OpExpr *clause, GinQualCounts *counts)
|
||||
operand = NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
/* aggressively reduce to a constant, and look through relabeling */
|
||||
operand = estimate_expression_value(root, operand);
|
||||
|
||||
if (IsA(operand, RelabelType))
|
||||
operand = (Node *) ((RelabelType *) operand)->arg;
|
||||
|
||||
@ -6918,7 +6926,8 @@ gincost_opexpr(IndexOptInfo *index, OpExpr *clause, GinQualCounts *counts)
|
||||
* by N, causing gincostestimate to scale up its estimates accordingly.
|
||||
*/
|
||||
static bool
|
||||
gincost_scalararrayopexpr(IndexOptInfo *index, ScalarArrayOpExpr *clause,
|
||||
gincost_scalararrayopexpr(PlannerInfo *root,
|
||||
IndexOptInfo *index, ScalarArrayOpExpr *clause,
|
||||
double numIndexEntries,
|
||||
GinQualCounts *counts)
|
||||
{
|
||||
@ -6943,6 +6952,9 @@ gincost_scalararrayopexpr(IndexOptInfo *index, ScalarArrayOpExpr *clause,
|
||||
if ((indexcol = find_index_column(leftop, index)) < 0)
|
||||
elog(ERROR, "could not match index to operand");
|
||||
|
||||
/* aggressively reduce to a constant, and look through relabeling */
|
||||
rightop = estimate_expression_value(root, rightop);
|
||||
|
||||
if (IsA(rightop, RelabelType))
|
||||
rightop = (Node *) ((RelabelType *) rightop)->arg;
|
||||
|
||||
@ -7160,7 +7172,8 @@ gincostestimate(PG_FUNCTION_ARGS)
|
||||
clause = rinfo->clause;
|
||||
if (IsA(clause, OpExpr))
|
||||
{
|
||||
matchPossible = gincost_opexpr(index,
|
||||
matchPossible = gincost_opexpr(root,
|
||||
index,
|
||||
(OpExpr *) clause,
|
||||
&counts);
|
||||
if (!matchPossible)
|
||||
@ -7168,7 +7181,8 @@ gincostestimate(PG_FUNCTION_ARGS)
|
||||
}
|
||||
else if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
matchPossible = gincost_scalararrayopexpr(index,
|
||||
matchPossible = gincost_scalararrayopexpr(root,
|
||||
index,
|
||||
(ScalarArrayOpExpr *) clause,
|
||||
numEntries,
|
||||
&counts);
|
||||
|
Reference in New Issue
Block a user