diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index badd31a44c..0543f6fffc 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -1397,6 +1397,27 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context, List *prefix = NIL; List *pc_steps; + /* + * If this is a clause for the first partition key, + * there are no preceding expressions; generate a + * pruning step without a prefix. + */ + if (pc->keyno == 0) + { + Assert(pc->op_strategy == strat); + pc_steps = get_steps_using_prefix(context, strat, + pc->op_is_ne, + pc->expr, + pc->cmpfn, + 0, + NULL, + NIL); + opsteps = list_concat(opsteps, pc_steps); + continue; + } + + Assert(pc->keyno > 0); + /* * Expressions from = clauses can always be in the * prefix, provided they're from an earlier key. @@ -1455,19 +1476,29 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context, * generate multiple steps, one for each combination * of the expressions for different keys. * + * If prefix contains no clauses, we would not have + * clauses for a valid subset of the partition keys + * for the remaining clauses; give up on generating + * pruning steps further for the strategy. + * * Note that we pass NULL for step_nullkeys, because * we don't search list/range partition bounds where * some keys are NULL. */ - Assert(pc->op_strategy == strat); - pc_steps = get_steps_using_prefix(context, strat, - pc->op_is_ne, - pc->expr, - pc->cmpfn, - pc->keyno, - NULL, - prefix); - opsteps = list_concat(opsteps, pc_steps); + if (prefix) + { + Assert(pc->op_strategy == strat); + pc_steps = get_steps_using_prefix(context, strat, + pc->op_is_ne, + pc->expr, + pc->cmpfn, + pc->keyno, + NULL, + prefix); + opsteps = list_concat(opsteps, pc_steps); + } + else + break; } } break; diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index 4315e8e0a3..d0f3b4525d 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -3671,3 +3671,12 @@ explain (costs off) update listp1 set a = 1 where a = 2; reset constraint_exclusion; reset enable_partition_pruning; drop table listp; +create table prefix_test (a int, b varchar) +partition by range(a, b); +create table prefix_test1 partition of prefix_test +for values from (1, 'a') to (1, 'b'); +select * from prefix_test where a <= 1 and b = 'a' ; + a | b +---+--- +(0 rows) + diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index 6658455a74..3581b6a0d3 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -1050,3 +1050,11 @@ reset constraint_exclusion; reset enable_partition_pruning; drop table listp; + +create table prefix_test (a int, b varchar) +partition by range(a, b); + +create table prefix_test1 partition of prefix_test +for values from (1, 'a') to (1, 'b'); + +select * from prefix_test where a <= 1 and b = 'a' ;