PG11-get_relation_constraints-fix.patch

text/plain

Filename: PG11-get_relation_constraints-fix.patch
Type: text/plain
Part: 1
Message: Re: speeding up planning with partitions

Patch

Format: unified
File+
src/backend/optimizer/util/plancat.c 7 3
src/test/regress/expected/partition_prune.out 41 0
src/test/regress/sql/partition_prune.sql 18 0
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;