diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 8369e3ad62..8428fe37bb 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1269,10 +1269,14 @@ get_relation_constraints(PlannerInfo *root, * Append partition predicates, if any. * * For selects, partition pruning uses the parent table's partition bound - * descriptor, instead of constraint exclusion which is driven by the - * individual partition's partition constraint. + * descriptor, so there's no need to include the partition constraint for + * this case. However, if the partition is referenced directly in the + * query then no partition pruning will occur, so we'll include it in that + * case. */ - if (enable_partition_pruning && root->parse->commandType != CMD_SELECT) + if ((root->parse->commandType != CMD_SELECT && enable_partition_pruning) || + (root->parse->commandType == CMD_SELECT && + rel->reloptkind == RELOPT_BASEREL)) { List *pcqual = RelationGetPartitionQual(relation); diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index 79e29e762b..02f8ceaa26 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -3417,4 +3417,45 @@ select * from listp where a = (select 2) and b <> 10; Filter: ((b <> 10) AND (a = $0)) (5 rows) +-- +-- check that a partition directly accessed in a query is excluded with +-- constraint_exclusion = on +-- +-- turn off partition pruning, so that it doesn't interfere +set enable_partition_pruning to off; +-- constraint exclusion doesn't apply +set constraint_exclusion to 'partition'; +explain (costs off) select * from listp1 where a = 2; + QUERY PLAN +-------------------- + Seq Scan on listp1 + Filter: (a = 2) +(2 rows) + +explain (costs off) select * from listp2 where a = 1; + QUERY PLAN +----------------------------- + Append + -> Seq Scan on listp2_10 + Filter: (a = 1) +(3 rows) + +-- constraint exclusion applies +set constraint_exclusion to 'on'; +explain (costs off) select * from listp1 where a = 2; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +explain (costs off) select * from listp2 where a = 1; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +reset constraint_exclusion; +reset enable_partition_pruning; drop table listp; diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index 6aecf25f46..cf56898e59 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -899,4 +899,22 @@ create table listp2_10 partition of listp2 for values in (10); explain (analyze, costs off, summary off, timing off) select * from listp where a = (select 2) and b <> 10; +-- +-- check that a partition directly accessed in a query is excluded with +-- constraint_exclusion = on +-- + +-- turn off partition pruning, so that it doesn't interfere +set enable_partition_pruning to off; + +-- constraint exclusion doesn't apply +set constraint_exclusion to 'partition'; +explain (costs off) select * from listp1 where a = 2; +explain (costs off) select * from listp2 where a = 1; +-- constraint exclusion applies +set constraint_exclusion to 'on'; +explain (costs off) select * from listp1 where a = 2; +explain (costs off) select * from listp2 where a = 1; +reset constraint_exclusion; +reset enable_partition_pruning; drop table listp;