boolpart_scan_nullpart.patch
application/octet-stream
Filename: boolpart_scan_nullpart.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/partitioning/partprune.c | 16 | 3 |
| src/include/partitioning/partprune.h | 5 | 4 |
| src/test/regress/expected/partition_prune.out | 15 | 10 |
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 510145e3c0..5b138e1c12 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -122,6 +122,7 @@ typedef struct GeneratePruningStepsContext
bool contradictory; /* clauses were proven self-contradictory */
/* Working state: */
int next_step_id;
+ bool has_is_not_op;
} GeneratePruningStepsContext;
/* The result of performing one PartitionPruneStep */
@@ -201,7 +202,8 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily,
Expr *clause,
Expr *partkey,
- Expr **outconst);
+ Expr **outconst,
+ bool *has_is_not_op);
static void partkey_datum_from_expr(PartitionPruneContext *context,
Expr *expr, int stateidx,
Datum *value, bool *isnull);
@@ -776,6 +778,8 @@ prune_append_rel_partitions(RelOptInfo *rel)
if (!enable_partition_pruning || clauses == NIL)
return bms_add_range(NULL, 0, rel->nparts - 1);
+ gcontext.has_is_not_op = false;
+
/*
* Process clauses to extract pruning steps that are usable at plan time.
* If the clauses are found to be contradictory, we can return the empty
@@ -807,6 +811,7 @@ prune_append_rel_partitions(RelOptInfo *rel)
context.planstate = NULL;
context.exprcontext = NULL;
context.exprstates = NULL;
+ context.has_is_not_op = gcontext.has_is_not_op;
/* Actual pruning happens here. */
return get_matching_partitions(&context, pruning_steps);
@@ -910,6 +915,10 @@ get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
result = bms_add_member(result, partindex);
}
+ if (context->has_is_not_op && context->boundinfo->null_index != -1)
+ result = bms_add_member(result, context->boundinfo->null_index);
+ else if (context->has_is_not_op)
+ scan_default |= partition_bound_has_default(context->boundinfo);
/* Add the null and/or default partition if needed and present. */
if (final_result->scan_null)
@@ -1814,7 +1823,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
* Recognize specially shaped clauses that match a Boolean partition key.
*/
boolmatchstatus = match_boolean_partition_clause(partopfamily, clause,
- partkey, &expr);
+ partkey, &expr, &context->has_is_not_op);
if (boolmatchstatus == PARTCLAUSE_MATCH_CLAUSE)
{
@@ -3596,7 +3605,7 @@ perform_pruning_combine_step(PartitionPruneContext *context,
*/
static PartClauseMatchStatus
match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
- Expr **outconst)
+ Expr **outconst, bool *has_is_not_op)
{
Expr *leftop;
@@ -3618,6 +3627,10 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
btest->booltesttype == IS_NOT_UNKNOWN)
return PARTCLAUSE_UNSUPPORTED;
+ if (btest->booltesttype == IS_NOT_TRUE ||
+ btest->booltesttype == IS_NOT_FALSE)
+ *has_is_not_op = true;
+
leftop = btest->arg;
if (IsA(leftop, RelabelType))
leftop = ((RelabelType *) leftop)->arg;
diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h
index c0d6889d47..d8f72a0146 100644
--- a/src/include/partitioning/partprune.h
+++ b/src/include/partitioning/partprune.h
@@ -59,6 +59,7 @@ typedef struct PartitionPruneContext
PlanState *planstate;
ExprContext *exprcontext;
ExprState **exprstates;
+ bool has_is_not_op;
} PartitionPruneContext;
/*
@@ -70,10 +71,10 @@ typedef struct PartitionPruneContext
#define PruneCxtStateIdx(partnatts, step_id, keyno) \
((partnatts) * (step_id) + (keyno))
-extern int make_partition_pruneinfo(struct PlannerInfo *root,
- struct RelOptInfo *parentrel,
- List *subpaths,
- List *prunequal);
+extern int make_partition_pruneinfo(struct PlannerInfo *root,
+ struct RelOptInfo *parentrel,
+ List *subpaths,
+ List *prunequal);
extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel);
extern Bitmapset *get_matching_partitions(PartitionPruneContext *context,
List *pruning_steps);
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index d700c00629..55cc528e55 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -1070,20 +1070,25 @@ explain (costs off) select * from boolpart where a is true or a is not true;
Filter: ((a IS TRUE) OR (a IS NOT TRUE))
-> Seq Scan on boolpart_t boolpart_2
Filter: ((a IS TRUE) OR (a IS NOT TRUE))
-(5 rows)
+ -> Seq Scan on boolpart_default boolpart_3
+ Filter: ((a IS TRUE) OR (a IS NOT TRUE))
+(7 rows)
explain (costs off) select * from boolpart where a is not true;
- QUERY PLAN
----------------------------------
- Seq Scan on boolpart_f boolpart
- Filter: (a IS NOT TRUE)
-(2 rows)
+ QUERY PLAN
+-----------------------------------------------
+ Append
+ -> Seq Scan on boolpart_f boolpart_1
+ Filter: (a IS NOT TRUE)
+ -> Seq Scan on boolpart_default boolpart_2
+ Filter: (a IS NOT TRUE)
+(5 rows)
explain (costs off) select * from boolpart where a is not true and a is not false;
- QUERY PLAN
---------------------------
- Result
- One-Time Filter: false
+ QUERY PLAN
+--------------------------------------------------
+ Seq Scan on boolpart_default boolpart
+ Filter: ((a IS NOT TRUE) AND (a IS NOT FALSE))
(2 rows)
explain (costs off) select * from boolpart where a is unknown;