mirror of https://github.com/postgres/postgres
Fix breakage of bitmap scan plan creation for special index operators such
as LIKE. I oversimplified this code when removing support for plan-time determination of index operator lossiness back in April --- I had thought create_bitmap_subplan could stop returning two separate lists of qual conditions, but it still must so that we can treat special operators correctly in create_bitmap_scan_plan. Per report from Rushabh Lathia.
This commit is contained in:
parent
6c3690d835
commit
176961c1f1
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.251 2008/10/21 20:42:53 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.252 2008/11/20 19:52:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -53,7 +53,7 @@ static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
BitmapHeapPath *best_path,
|
BitmapHeapPath *best_path,
|
||||||
List *tlist, List *scan_clauses);
|
List *tlist, List *scan_clauses);
|
||||||
static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
List **qual);
|
List **qual, List **indexqual);
|
||||||
static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
|
static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
|
||||||
List *tlist, List *scan_clauses);
|
List *tlist, List *scan_clauses);
|
||||||
static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
|
static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
|
||||||
|
@ -987,6 +987,7 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
Index baserelid = best_path->path.parent->relid;
|
Index baserelid = best_path->path.parent->relid;
|
||||||
Plan *bitmapqualplan;
|
Plan *bitmapqualplan;
|
||||||
List *bitmapqualorig;
|
List *bitmapqualorig;
|
||||||
|
List *indexquals;
|
||||||
List *qpqual;
|
List *qpqual;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
BitmapHeapScan *scan_plan;
|
BitmapHeapScan *scan_plan;
|
||||||
|
@ -995,9 +996,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
Assert(baserelid > 0);
|
Assert(baserelid > 0);
|
||||||
Assert(best_path->path.parent->rtekind == RTE_RELATION);
|
Assert(best_path->path.parent->rtekind == RTE_RELATION);
|
||||||
|
|
||||||
/* Process the bitmapqual tree into a Plan tree and qual list */
|
/* Process the bitmapqual tree into a Plan tree and qual lists */
|
||||||
bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
|
bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
|
||||||
&bitmapqualorig);
|
&bitmapqualorig, &indexquals);
|
||||||
|
|
||||||
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
|
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
|
||||||
scan_clauses = extract_actual_clauses(scan_clauses, false);
|
scan_clauses = extract_actual_clauses(scan_clauses, false);
|
||||||
|
@ -1021,7 +1022,7 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
* (either by the index itself, or by nodeBitmapHeapscan.c), but if there
|
* (either by the index itself, or by nodeBitmapHeapscan.c), but if there
|
||||||
* are any "special" operators involved then they must be added to qpqual.
|
* are any "special" operators involved then they must be added to qpqual.
|
||||||
* The upshot is that qpqual must contain scan_clauses minus whatever
|
* The upshot is that qpqual must contain scan_clauses minus whatever
|
||||||
* appears in bitmapqualorig.
|
* appears in indexquals.
|
||||||
*
|
*
|
||||||
* In normal cases simple equal() checks will be enough to spot duplicate
|
* In normal cases simple equal() checks will be enough to spot duplicate
|
||||||
* clauses, so we try that first. In some situations (particularly with
|
* clauses, so we try that first. In some situations (particularly with
|
||||||
|
@ -1033,22 +1034,22 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
*
|
*
|
||||||
* Unlike create_indexscan_plan(), we need take no special thought here
|
* Unlike create_indexscan_plan(), we need take no special thought here
|
||||||
* for partial index predicates; this is because the predicate conditions
|
* for partial index predicates; this is because the predicate conditions
|
||||||
* are already listed in bitmapqualorig. Bitmap scans have to do it that
|
* are already listed in bitmapqualorig and indexquals. Bitmap scans have
|
||||||
* way because predicate conditions need to be rechecked if the scan's
|
* to do it that way because predicate conditions need to be rechecked if
|
||||||
* bitmap becomes lossy.
|
* the scan becomes lossy.
|
||||||
*/
|
*/
|
||||||
qpqual = NIL;
|
qpqual = NIL;
|
||||||
foreach(l, scan_clauses)
|
foreach(l, scan_clauses)
|
||||||
{
|
{
|
||||||
Node *clause = (Node *) lfirst(l);
|
Node *clause = (Node *) lfirst(l);
|
||||||
|
|
||||||
if (list_member(bitmapqualorig, clause))
|
if (list_member(indexquals, clause))
|
||||||
continue;
|
continue;
|
||||||
if (!contain_mutable_functions(clause))
|
if (!contain_mutable_functions(clause))
|
||||||
{
|
{
|
||||||
List *clausel = list_make1(clause);
|
List *clausel = list_make1(clause);
|
||||||
|
|
||||||
if (predicate_implied_by(clausel, bitmapqualorig))
|
if (predicate_implied_by(clausel, indexquals))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
qpqual = lappend(qpqual, clause);
|
qpqual = lappend(qpqual, clause);
|
||||||
|
@ -1082,19 +1083,21 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||||
/*
|
/*
|
||||||
* Given a bitmapqual tree, generate the Plan tree that implements it
|
* Given a bitmapqual tree, generate the Plan tree that implements it
|
||||||
*
|
*
|
||||||
* As a byproduct, we also return in *qual a qual list (in implicit-AND
|
* As byproducts, we also return in *qual and *indexqual the qual lists
|
||||||
* form, without RestrictInfos) describing the generated indexqual
|
* (in implicit-AND form, without RestrictInfos) describing the original index
|
||||||
* conditions, as needed for rechecking heap tuples in lossy cases.
|
* conditions and the generated indexqual conditions. (These are the same in
|
||||||
* This list also includes partial-index predicates, because we have to
|
* simple cases, but when special index operators are involved, the former
|
||||||
* recheck predicates as well as index conditions if the scan's bitmap
|
* list includes the special conditions while the latter includes the actual
|
||||||
* becomes lossy.
|
* indexable conditions derived from them.) Both lists include partial-index
|
||||||
|
* predicates, because we have to recheck predicates as well as index
|
||||||
|
* conditions if the bitmap scan becomes lossy.
|
||||||
*
|
*
|
||||||
* Note: if you find yourself changing this, you probably need to change
|
* Note: if you find yourself changing this, you probably need to change
|
||||||
* make_restrictinfo_from_bitmapqual too.
|
* make_restrictinfo_from_bitmapqual too.
|
||||||
*/
|
*/
|
||||||
static Plan *
|
static Plan *
|
||||||
create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
List **qual)
|
List **qual, List **indexqual)
|
||||||
{
|
{
|
||||||
Plan *plan;
|
Plan *plan;
|
||||||
|
|
||||||
|
@ -1103,6 +1106,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
|
BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
|
||||||
List *subplans = NIL;
|
List *subplans = NIL;
|
||||||
List *subquals = NIL;
|
List *subquals = NIL;
|
||||||
|
List *subindexquals = NIL;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1116,11 +1120,13 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
{
|
{
|
||||||
Plan *subplan;
|
Plan *subplan;
|
||||||
List *subqual;
|
List *subqual;
|
||||||
|
List *subindexqual;
|
||||||
|
|
||||||
subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
|
subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
|
||||||
&subqual);
|
&subqual, &subindexqual);
|
||||||
subplans = lappend(subplans, subplan);
|
subplans = lappend(subplans, subplan);
|
||||||
subquals = list_concat_unique(subquals, subqual);
|
subquals = list_concat_unique(subquals, subqual);
|
||||||
|
subindexquals = list_concat_unique(subindexquals, subindexqual);
|
||||||
}
|
}
|
||||||
plan = (Plan *) make_bitmap_and(subplans);
|
plan = (Plan *) make_bitmap_and(subplans);
|
||||||
plan->startup_cost = apath->path.startup_cost;
|
plan->startup_cost = apath->path.startup_cost;
|
||||||
|
@ -1129,13 +1135,16 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
|
clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
|
||||||
plan->plan_width = 0; /* meaningless */
|
plan->plan_width = 0; /* meaningless */
|
||||||
*qual = subquals;
|
*qual = subquals;
|
||||||
|
*indexqual = subindexquals;
|
||||||
}
|
}
|
||||||
else if (IsA(bitmapqual, BitmapOrPath))
|
else if (IsA(bitmapqual, BitmapOrPath))
|
||||||
{
|
{
|
||||||
BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
|
BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
|
||||||
List *subplans = NIL;
|
List *subplans = NIL;
|
||||||
List *subquals = NIL;
|
List *subquals = NIL;
|
||||||
|
List *subindexquals = NIL;
|
||||||
bool const_true_subqual = false;
|
bool const_true_subqual = false;
|
||||||
|
bool const_true_subindexqual = false;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1151,15 +1160,21 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
{
|
{
|
||||||
Plan *subplan;
|
Plan *subplan;
|
||||||
List *subqual;
|
List *subqual;
|
||||||
|
List *subindexqual;
|
||||||
|
|
||||||
subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
|
subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
|
||||||
&subqual);
|
&subqual, &subindexqual);
|
||||||
subplans = lappend(subplans, subplan);
|
subplans = lappend(subplans, subplan);
|
||||||
if (subqual == NIL)
|
if (subqual == NIL)
|
||||||
const_true_subqual = true;
|
const_true_subqual = true;
|
||||||
else if (!const_true_subqual)
|
else if (!const_true_subqual)
|
||||||
subquals = lappend(subquals,
|
subquals = lappend(subquals,
|
||||||
make_ands_explicit(subqual));
|
make_ands_explicit(subqual));
|
||||||
|
if (subindexqual == NIL)
|
||||||
|
const_true_subindexqual = true;
|
||||||
|
else if (!const_true_subindexqual)
|
||||||
|
subindexquals = lappend(subindexquals,
|
||||||
|
make_ands_explicit(subindexqual));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1191,6 +1206,12 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
*qual = subquals;
|
*qual = subquals;
|
||||||
else
|
else
|
||||||
*qual = list_make1(make_orclause(subquals));
|
*qual = list_make1(make_orclause(subquals));
|
||||||
|
if (const_true_subindexqual)
|
||||||
|
*indexqual = NIL;
|
||||||
|
else if (list_length(subindexquals) <= 1)
|
||||||
|
*indexqual = subindexquals;
|
||||||
|
else
|
||||||
|
*indexqual = list_make1(make_orclause(subindexquals));
|
||||||
}
|
}
|
||||||
else if (IsA(bitmapqual, IndexPath))
|
else if (IsA(bitmapqual, IndexPath))
|
||||||
{
|
{
|
||||||
|
@ -1211,6 +1232,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
|
clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
|
||||||
plan->plan_width = 0; /* meaningless */
|
plan->plan_width = 0; /* meaningless */
|
||||||
*qual = get_actual_clauses(ipath->indexclauses);
|
*qual = get_actual_clauses(ipath->indexclauses);
|
||||||
|
*indexqual = get_actual_clauses(ipath->indexquals);
|
||||||
foreach(l, ipath->indexinfo->indpred)
|
foreach(l, ipath->indexinfo->indpred)
|
||||||
{
|
{
|
||||||
Expr *pred = (Expr *) lfirst(l);
|
Expr *pred = (Expr *) lfirst(l);
|
||||||
|
@ -1222,7 +1244,10 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||||
* generating redundant conditions.
|
* generating redundant conditions.
|
||||||
*/
|
*/
|
||||||
if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
|
if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
|
||||||
|
{
|
||||||
*qual = lappend(*qual, pred);
|
*qual = lappend(*qual, pred);
|
||||||
|
*indexqual = lappend(*indexqual, pred);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -98,3 +98,32 @@ SELECT b.*
|
||||||
4500 | 2080851358
|
4500 | 2080851358
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Check correct optimization of LIKE (special index operator support)
|
||||||
|
-- for both indexscan and bitmapscan cases
|
||||||
|
--
|
||||||
|
set enable_seqscan to false;
|
||||||
|
set enable_indexscan to true;
|
||||||
|
set enable_bitmapscan to false;
|
||||||
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||||
|
proname
|
||||||
|
------------------------
|
||||||
|
RI_FKey_cascade_del
|
||||||
|
RI_FKey_noaction_del
|
||||||
|
RI_FKey_restrict_del
|
||||||
|
RI_FKey_setdefault_del
|
||||||
|
RI_FKey_setnull_del
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
set enable_indexscan to false;
|
||||||
|
set enable_bitmapscan to true;
|
||||||
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||||
|
proname
|
||||||
|
------------------------
|
||||||
|
RI_FKey_cascade_del
|
||||||
|
RI_FKey_noaction_del
|
||||||
|
RI_FKey_restrict_del
|
||||||
|
RI_FKey_setdefault_del
|
||||||
|
RI_FKey_setnull_del
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
|
|
@ -51,3 +51,16 @@ SELECT b.*
|
||||||
FROM bt_f8_heap b
|
FROM bt_f8_heap b
|
||||||
WHERE b.seqno = '4500'::float8;
|
WHERE b.seqno = '4500'::float8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Check correct optimization of LIKE (special index operator support)
|
||||||
|
-- for both indexscan and bitmapscan cases
|
||||||
|
--
|
||||||
|
|
||||||
|
set enable_seqscan to false;
|
||||||
|
set enable_indexscan to true;
|
||||||
|
set enable_bitmapscan to false;
|
||||||
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||||
|
|
||||||
|
set enable_indexscan to false;
|
||||||
|
set enable_bitmapscan to true;
|
||||||
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
||||||
|
|
Loading…
Reference in New Issue