From 37c861d5eae1c8f11b3fae93cb209da262a13fbc Mon Sep 17 00:00:00 2001 From: amit Date: Tue, 13 Dec 2016 15:07:41 +0900 Subject: [PATCH 1/8] Fix a bug of insertion into an internal partition. Since implicit partition constraints are not inherited, an internal partition's constraint was not being enforced when targeted directly. So, include such constraint when setting up leaf partition result relations for tuple-routing. Reported by: n/a Patch by: Amit Langote Reports: n/a --- src/backend/commands/copy.c | 1 - src/backend/commands/tablecmds.c | 1 - src/backend/executor/execMain.c | 42 ++++++++++++++++++++++++++++-------- src/include/executor/executor.h | 1 - src/test/regress/expected/insert.out | 6 ++++++ src/test/regress/sql/insert.sql | 5 +++++ 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 1fd2162794..75386212e0 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -2432,7 +2432,6 @@ CopyFrom(CopyState cstate) InitResultRelInfo(resultRelInfo, cstate->rel, 1, /* dummy rangetable index */ - true, /* do load partition check expression */ NULL, 0); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e633a50dd2..06e43cbb3a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1324,7 +1324,6 @@ ExecuteTruncate(TruncateStmt *stmt) InitResultRelInfo(resultRelInfo, rel, 0, /* dummy rangetable index */ - false, NULL, 0); resultRelInfo++; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index ff277d300a..5457f8fbde 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -824,10 +824,10 @@ InitPlan(QueryDesc *queryDesc, int eflags) resultRelationOid = getrelid(resultRelationIndex, rangeTable); resultRelation = heap_open(resultRelationOid, RowExclusiveLock); + InitResultRelInfo(resultRelInfo, resultRelation, resultRelationIndex, - true, NULL, estate->es_instrument); resultRelInfo++; @@ -1218,10 +1218,11 @@ void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, - bool load_partition_check, Relation partition_root, int instrument_options) { + List *partition_check = NIL; + MemSet(resultRelInfo, 0, sizeof(ResultRelInfo)); resultRelInfo->type = T_ResultRelInfo; resultRelInfo->ri_RangeTableIndex = resultRelationIndex; @@ -1257,13 +1258,38 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, resultRelInfo->ri_ConstraintExprs = NULL; resultRelInfo->ri_junkFilter = 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 - * partitions for tuple-routing. + * If partition_root has been specified, that means we are builiding the + * 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; } @@ -1327,7 +1353,6 @@ ExecGetTriggerResultRel(EState *estate, Oid relid) InitResultRelInfo(rInfo, rel, 0, /* dummy rangetable index */ - true, NULL, estate->es_instrument); estate->es_trig_target_relations = @@ -3132,7 +3157,6 @@ ExecSetupPartitionTupleRouting(Relation rel, InitResultRelInfo(leaf_part_rri, partrel, 1, /* dummy */ - false, rel, 0); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index d424031676..eb180fdb63 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -189,7 +189,6 @@ extern void CheckValidResultRel(Relation resultRel, CmdType operation); extern void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, - bool load_partition_check, Relation partition_root, int instrument_options); extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid); diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index 0382560d39..729d9ebbbc 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -358,5 +358,11 @@ alter table p add constraint check_b check (b = 3); insert into p values (1, 2); ERROR: new row for relation "p11" violates check constraint "check_b" 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 drop table p, p1, p11; diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index a6eab8f365..5509555fc5 100644 --- a/src/test/regress/sql/insert.sql +++ b/src/test/regress/sql/insert.sql @@ -221,5 +221,10 @@ alter table p add constraint check_b check (b = 3); -- after "(1, 2)" is routed to it 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 drop table p, p1, p11; -- 2.11.0