Thanks for this fix! Looking into it now.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/backend/executor/execPartition.c
b/src/backend/executor/execPartition.c
index 4d34734a45..fe42670e0a 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -52,11 +52,9 @@
* indexed.
*
* nonleaf_partitions
- * Array of 'max_dispatch' elements containing pointers to
- * ResultRelInfos of nonleaf partitions touched by tuple routing.
These
- * are currently only used for checking the partition's constraint
if
- * the nonleaf partition happens to be a default partition of its
- * parent
+ * Array of 'max_dispatch' elements containing pointers to fake
+ * ResultRelInfo objects for nonleaf partitions, useful for
checking
+ * the partition constraint.
*
* num_dispatch
* The current number of items stored in the
'partition_dispatch_info'
@@ -305,7 +303,7 @@ ExecFindPartition(ModifyTableState *mtstate,
/* start with the root partitioned table */
dispatch = pd[0];
- while (true)
+ do
{
AttrNumber *map = dispatch->tupmap;
int partidx = -1;
@@ -455,22 +453,12 @@ ExecFindPartition(ModifyTableState *mtstate,
/*
* If this partition is the default one, we must check its
partition
- * constraint, because it may have changed due to partitions
being
- * added to the parent concurrently. We do the check here
instead of
- * in ExecInsert(), because we would not want to miss checking
the
- * constraint of any nonleaf partitions as they never make it to
- * ExecInsert().
+ * constraint now, which may have changed due to partitions
being
+ * added to the parent concurrently.
*/
if (partidx == partdesc->boundinfo->default_index)
- {
- Assert(rri != NULL);
ExecPartitionCheck(rri, slot, estate, true);
- }
-
- /* Break out and return if we've found the leaf partition. */
- if (dispatch == NULL)
- break;
- }
+ } while (dispatch != NULL);
MemoryContextSwitchTo(oldcxt);
ecxt->ecxt_scantuple = ecxt_scantuple_old;
@@ -1037,7 +1025,6 @@ ExecInitPartitionDispatchInfo(EState *estate,
Relation rel;
PartitionDesc partdesc;
PartitionDispatch pd;
- ResultRelInfo *rri = NULL;
int dispatchidx;
MemoryContext oldcxt;
@@ -1123,6 +1110,19 @@ ExecInitPartitionDispatchInfo(EState *estate,
}
proute->partition_dispatch_info[dispatchidx] = pd;
+ /*
+ * If setting up a PartitionDispatch for a sub-partitioned table, we may
+ * also need a fake ResultRelInfo for checking the partition constraint
+ * later; set that up now.
+ */
+ if (parent_pd)
+ {
+ ResultRelInfo *rri = makeNode(ResultRelInfo);
+
+ InitResultRelInfo(rri, rel, 1, proute->partition_root, 0);
+ proute->nonleaf_partitions[dispatchidx] = rri;
+ }
+
/*
* Finally, if setting up a PartitionDispatch for a sub-partitioned
table,
* install a downlink in the parent to allow quick descent.
@@ -1133,17 +1133,6 @@ ExecInitPartitionDispatchInfo(EState *estate,
parent_pd->indexes[partidx] = dispatchidx;
}
- /*
- * Also create a minimally valid ResultRelInfo to check the partition's
- * partition's constraint.
- */
- if (rel->rd_rel->relispartition)
- {
- rri = makeNode(ResultRelInfo);
- InitResultRelInfo(rri, rel, 1, proute->partition_root, 0);
- }
- proute->nonleaf_partitions[dispatchidx] = rri;
-
MemoryContextSwitchTo(oldcxt);
return pd;