diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/partitioning/partprune.c | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index cdc61a89974..354eb0d4e60 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -853,54 +853,60 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context, } } - /* - * If generate_opsteps is set to false it means no OpExprs were directly - * present in the input list. + /*----------- + * Now generate some (more) pruning steps. We have three strategies: + * + * 1) Generate pruning steps based on IS NULL clauses: + * a) For list partitioning, null partition keys can only be found in + * the designated null-accepting partition, so if there are IS NULL + * clauses containing partition keys we should generate a pruning + * step that gets rid of all partitions but that one. We can + * disregard any OpExpr we may have found. + * b) For range partitioning, only the default partition can contain + * NULL values, so the same rationale applies. + * c) For hash partitioning, we only apply this strategy if we have + * IS NULL clauses for all the keys. Strategy 2 below will take + * care of the case where some keys have OpExprs and others have + * IS NULL clauses. + * + * 2) If not, generate steps based on OpExprs we have (if any). + * + * 3) If this doesn't work either, we may be able to generate steps to + * prune just the null-accepting partition (if one exists), if we have + * IS NOT NULL clauses for all partition keys. */ - if (!generate_opsteps) + if (!bms_is_empty(nullkeys) && + (part_scheme->strategy == PARTITION_STRATEGY_LIST || + part_scheme->strategy == PARTITION_STRATEGY_RANGE || + (part_scheme->strategy == PARTITION_STRATEGY_HASH && + bms_num_members(nullkeys) == part_scheme->partnatts))) { - /* - * Generate one prune step for the information derived from IS NULL, - * if any. To prune hash partitions, we must have found IS NULL - * clauses for all partition keys. - */ - if (!bms_is_empty(nullkeys) && - (part_scheme->strategy != PARTITION_STRATEGY_HASH || - bms_num_members(nullkeys) == part_scheme->partnatts)) - { - PartitionPruneStep *step; - - step = gen_prune_step_op(context, InvalidStrategy, - false, NIL, NIL, nullkeys); - result = lappend(result, step); - } - - /* - * Note that for IS NOT NULL clauses, simply having step suffices; - * there is no need to propagate the exact details of which keys are - * required to be NOT NULL. Hash partitioning expects to see actual - * values to perform any pruning. - */ - if (!bms_is_empty(notnullkeys) && - part_scheme->strategy != PARTITION_STRATEGY_HASH) - { - PartitionPruneStep *step; + PartitionPruneStep *step; - step = gen_prune_step_op(context, InvalidStrategy, - false, NIL, NIL, NULL); - result = lappend(result, step); - } + /* Strategy 1 */ + step = gen_prune_step_op(context, InvalidStrategy, + false, NIL, NIL, nullkeys); + result = lappend(result, step); } - else + else if (generate_opsteps) { PartitionPruneStep *step; - /* Generate pruning steps from OpExpr clauses in keyclauses. */ + /* Strategy 2 */ step = gen_prune_steps_from_opexps(part_scheme, context, keyclauses, nullkeys); if (step != NULL) result = lappend(result, step); } + else if (bms_num_members(notnullkeys) == part_scheme->partnatts) + { + PartitionPruneStep *step; + + /* Strategy 3 */ + step = gen_prune_step_op(context, InvalidStrategy, + false, NIL, NIL, NULL); + result = lappend(result, step); + } /* * Finally, results from all entries appearing in result should be |