Commit 39162b20 authored by Robert Haas's avatar Robert Haas

Fix failure to enforce partitioning contraint for internal partitions.

When a tuple is inherited into a partitioning root, no partition
constraints need to be enforced; when it is inserted into a leaf, the
parent's partitioning quals needed to be enforced.  The previous
coding got both of those cases right.  When a tuple is inserted into
an intermediate level of the partitioning hierarchy (i.e. a table
which is both a partition itself and in turn partitioned), it must
enforce the partitioning qual inherited from its parent.  That case
got overlooked; repair.

Amit Langote
parent bec96c82
...@@ -2432,7 +2432,6 @@ CopyFrom(CopyState cstate) ...@@ -2432,7 +2432,6 @@ CopyFrom(CopyState cstate)
InitResultRelInfo(resultRelInfo, InitResultRelInfo(resultRelInfo,
cstate->rel, cstate->rel,
1, /* dummy rangetable index */ 1, /* dummy rangetable index */
true, /* do load partition check expression */
NULL, NULL,
0); 0);
......
...@@ -1324,7 +1324,6 @@ ExecuteTruncate(TruncateStmt *stmt) ...@@ -1324,7 +1324,6 @@ ExecuteTruncate(TruncateStmt *stmt)
InitResultRelInfo(resultRelInfo, InitResultRelInfo(resultRelInfo,
rel, rel,
0, /* dummy rangetable index */ 0, /* dummy rangetable index */
false,
NULL, NULL,
0); 0);
resultRelInfo++; resultRelInfo++;
......
...@@ -824,10 +824,10 @@ InitPlan(QueryDesc *queryDesc, int eflags) ...@@ -824,10 +824,10 @@ InitPlan(QueryDesc *queryDesc, int eflags)
resultRelationOid = getrelid(resultRelationIndex, rangeTable); resultRelationOid = getrelid(resultRelationIndex, rangeTable);
resultRelation = heap_open(resultRelationOid, RowExclusiveLock); resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
InitResultRelInfo(resultRelInfo, InitResultRelInfo(resultRelInfo,
resultRelation, resultRelation,
resultRelationIndex, resultRelationIndex,
true,
NULL, NULL,
estate->es_instrument); estate->es_instrument);
resultRelInfo++; resultRelInfo++;
...@@ -1218,10 +1218,11 @@ void ...@@ -1218,10 +1218,11 @@ void
InitResultRelInfo(ResultRelInfo *resultRelInfo, InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation resultRelationDesc, Relation resultRelationDesc,
Index resultRelationIndex, Index resultRelationIndex,
bool load_partition_check,
Relation partition_root, Relation partition_root,
int instrument_options) int instrument_options)
{ {
List *partition_check = NIL;
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo)); MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
resultRelInfo->type = T_ResultRelInfo; resultRelInfo->type = T_ResultRelInfo;
resultRelInfo->ri_RangeTableIndex = resultRelationIndex; resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
...@@ -1257,13 +1258,38 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, ...@@ -1257,13 +1258,38 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_ConstraintExprs = NULL; resultRelInfo->ri_ConstraintExprs = NULL;
resultRelInfo->ri_junkFilter = NULL; resultRelInfo->ri_junkFilter = NULL;
resultRelInfo->ri_projectReturning = NULL; resultRelInfo->ri_projectReturning = NULL;
if (load_partition_check)
resultRelInfo->ri_PartitionCheck =
RelationGetPartitionQual(resultRelationDesc);
/* /*
* The following gets set to NULL unless we are initializing leaf * If partition_root has been specified, that means we are builiding the
* partitions for tuple-routing. * ResultRelationInfo for one of its leaf partitions. In that case, we
* need *not* initialize the leaf partition's constraint, but rather the
* the partition_root's (if any). We must do that explicitly like this,
* because implicit partition constraints are not inherited like user-
* defined constraints and would fail to be enforced by ExecConstraints()
* after a tuple is routed to a leaf partition.
*/ */
if (partition_root)
{
/*
* Root table itself may or may not be a partition; partition_check
* would be NIL in the latter case.
*/
partition_check = RelationGetPartitionQual(partition_root);
/*
* This is not our own partition constraint, but rather an ancestor's.
* So any Vars in it bear the ancestor's attribute numbers. We must
* switch them to our own.
*/
if (partition_check != NIL)
partition_check = map_partition_varattnos(partition_check,
resultRelationDesc,
partition_root);
}
else
partition_check = RelationGetPartitionQual(resultRelationDesc);
resultRelInfo->ri_PartitionCheck = partition_check;
resultRelInfo->ri_PartitionRoot = partition_root; resultRelInfo->ri_PartitionRoot = partition_root;
} }
...@@ -1327,7 +1353,6 @@ ExecGetTriggerResultRel(EState *estate, Oid relid) ...@@ -1327,7 +1353,6 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
InitResultRelInfo(rInfo, InitResultRelInfo(rInfo,
rel, rel,
0, /* dummy rangetable index */ 0, /* dummy rangetable index */
true,
NULL, NULL,
estate->es_instrument); estate->es_instrument);
estate->es_trig_target_relations = estate->es_trig_target_relations =
...@@ -3132,7 +3157,6 @@ ExecSetupPartitionTupleRouting(Relation rel, ...@@ -3132,7 +3157,6 @@ ExecSetupPartitionTupleRouting(Relation rel,
InitResultRelInfo(leaf_part_rri, InitResultRelInfo(leaf_part_rri,
partrel, partrel,
1, /* dummy */ 1, /* dummy */
false,
rel, rel,
0); 0);
......
...@@ -189,7 +189,6 @@ extern void CheckValidResultRel(Relation resultRel, CmdType operation); ...@@ -189,7 +189,6 @@ extern void CheckValidResultRel(Relation resultRel, CmdType operation);
extern void InitResultRelInfo(ResultRelInfo *resultRelInfo, extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation resultRelationDesc, Relation resultRelationDesc,
Index resultRelationIndex, Index resultRelationIndex,
bool load_partition_check,
Relation partition_root, Relation partition_root,
int instrument_options); int instrument_options);
extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid); extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
......
...@@ -358,5 +358,11 @@ alter table p add constraint check_b check (b = 3); ...@@ -358,5 +358,11 @@ alter table p add constraint check_b check (b = 3);
insert into p values (1, 2); insert into p values (1, 2);
ERROR: new row for relation "p11" violates check constraint "check_b" ERROR: new row for relation "p11" violates check constraint "check_b"
DETAIL: Failing row contains (1, 2). DETAIL: Failing row contains (1, 2).
-- check that inserting into an internal partition successfully results in
-- checking its partition constraint before inserting into the leaf partition
-- selected by tuple-routing
insert into p1 (a, b) values (2, 3);
ERROR: new row for relation "p11" violates partition constraint
DETAIL: Failing row contains (3, 2).
-- cleanup -- cleanup
drop table p, p1, p11; drop table p, p1, p11;
...@@ -221,5 +221,10 @@ alter table p add constraint check_b check (b = 3); ...@@ -221,5 +221,10 @@ alter table p add constraint check_b check (b = 3);
-- after "(1, 2)" is routed to it -- after "(1, 2)" is routed to it
insert into p values (1, 2); insert into p values (1, 2);
-- check that inserting into an internal partition successfully results in
-- checking its partition constraint before inserting into the leaf partition
-- selected by tuple-routing
insert into p1 (a, b) values (2, 3);
-- cleanup -- cleanup
drop table p, p1, p11; drop table p, p1, p11;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment