From 17e63c3aaa5df849634a2770fdf18a0e88e56b08 Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Mon, 7 Nov 2022 15:56:46 +0800 Subject: [PATCH v4] constant folding for indexquals in bitmap scan --- contrib/btree_gin/expected/bool.out | 2 +- src/backend/optimizer/plan/createplan.c | 47 +++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/contrib/btree_gin/expected/bool.out b/contrib/btree_gin/expected/bool.out index 207a3f2328..51a70eb530 100644 --- a/contrib/btree_gin/expected/bool.out +++ b/contrib/btree_gin/expected/bool.out @@ -92,7 +92,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i=true ORDER BY i; Sort Sort Key: i -> Bitmap Heap Scan on test_bool - Filter: i + Recheck Cond: i -> Bitmap Index Scan on idx_bool Index Cond: (i = true) (6 rows) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index ac86ce9003..ef50cf8b18 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -20,6 +20,7 @@ #include "access/sysattr.h" #include "catalog/pg_class.h" +#include "catalog/pg_operator.h" #include "foreign/fdwapi.h" #include "miscadmin.h" #include "nodes/extensible.h" @@ -3480,11 +3481,53 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, { IndexClause *iclause = (IndexClause *) lfirst(l); RestrictInfo *rinfo = iclause->rinfo; + ListCell *l2; Assert(!rinfo->pseudoconstant); subquals = lappend(subquals, rinfo->clause); - subindexquals = list_concat(subindexquals, - get_actual_clauses(iclause->indexquals)); + + /* + * The indexquals may have been transformed into form "indexkey = + * true/false" in match_boolean_index_clause. We need to + * re-simplify them in order to compare them to scan_clauses in + * create_bitmap_scan_plan. + * + * According to what match_boolean_index_clause does, the constant + * input can be only on right, and it cannot be a constant-NULL. + */ + foreach(l2, iclause->indexquals) + { + RestrictInfo *restrictinfo = lfirst_node(RestrictInfo, l2); + Node *clause = (Node *) restrictinfo->clause; + + Assert(!restrictinfo->pseudoconstant); + + if (is_opclause(clause) && + ((OpExpr *) clause)->opno == BooleanEqualOperator) + { + Node *rightop; + + Assert(list_length(((OpExpr *) clause)->args) == 2); + rightop = lsecond(((OpExpr *) clause)->args); + + /* + * The constant input can be only on right, and it cannot + * be a constant-NULL. + */ + if (rightop && IsA(rightop, Const)) + { + Node *leftop = linitial(((OpExpr *) clause)->args); + + Assert(!((Const *) rightop)->constisnull); + if (DatumGetBool(((Const *) rightop)->constvalue)) + clause = leftop; /* indexkey = true */ + else + clause = negate_clause(leftop); /* indexkey = false */ + } + } + + subindexquals = lappend(subindexquals, clause); + } if (rinfo->parent_ec) subindexECs = lappend(subindexECs, rinfo->parent_ec); } -- 2.31.0