summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execPartition.c39
-rw-r--r--src/test/regress/expected/insert.out41
-rw-r--r--src/test/regress/sql/insert.sql28
3 files changed, 93 insertions, 15 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 011e3cff1ad..8061c7e449d 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -253,16 +253,25 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
partdesc = RelationGetPartitionDesc(rel);
/*
- * Convert the tuple to this parent's layout, if different from the
- * current relation.
+ * Use the slot dedicated to this level's parent. All parents except
+ * the root have a dedicated slot. For the root parent, we just use
+ * the original input slot.
*/
- myslot = dispatch->tupslot;
- if (myslot != NULL && map != NULL)
+ myslot = dispatch->tupslot == NULL ? slot : dispatch->tupslot;
+
+ /*
+ * If the tuple layout of this level's parent is different from the
+ * previous level's parent, convert the tuple and store it into its
+ * dedicated slot.
+ */
+ if (myslot != slot)
{
- tuple = do_convert_tuple(tuple, map);
+ if (map != NULL)
+ tuple = do_convert_tuple(tuple, map);
ExecStoreTuple(tuple, myslot, InvalidBuffer, true);
- slot = myslot;
}
+ else
+ Assert(map == NULL);
/*
* Extract partition key from tuple. Expression evaluation machinery
@@ -272,8 +281,8 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
* partitioning level has different tuple descriptor from the parent.
* So update ecxt_scantuple accordingly.
*/
- ecxt->ecxt_scantuple = slot;
- FormPartitionKeyDatum(dispatch, slot, estate, values, isnull);
+ ecxt->ecxt_scantuple = myslot;
+ FormPartitionKeyDatum(dispatch, myslot, estate, values, isnull);
/*
* Nothing for get_partition_for_tuple() to do if there are no
@@ -309,19 +318,19 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
dispatch = pd[-dispatch->indexes[cur_index]];
/*
- * Release the dedicated slot, if it was used. Create a copy of
- * the tuple first, for the next iteration.
+ * Make a copy of the tuple for the next level of routing. If
+ * this level's parent had a dedicated slot, we must clear its
+ * tuple too, which would be the copy we made in the last
+ * iteration.
*/
- if (slot == myslot)
- {
- tuple = ExecCopySlotTuple(myslot);
+ tuple = ExecCopySlotTuple(myslot);
+ if (myslot != slot)
ExecClearTuple(myslot);
- }
}
}
/* Release the tuple in the lowest parent's dedicated slot. */
- if (slot == myslot)
+ if (myslot != slot)
ExecClearTuple(myslot);
/* A partition was not found. */
diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out
index 5edf2693679..13f53e36490 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -629,6 +629,47 @@ select tableoid::regclass, * from mlparted_def;
mlparted_defd | 70 | 100 |
(4 rows)
+-- Check multi-level tuple routing with attributes dropped from the
+-- top-most parent. First remove the last attribute.
+alter table mlparted add d int, add e int;
+alter table mlparted drop e;
+create table mlparted5 partition of mlparted
+ for values from (1, 40) to (1, 50) partition by range (c);
+create table mlparted5_ab partition of mlparted5
+ for values from ('a') to ('c') partition by list (c);
+create table mlparted5_a partition of mlparted5_ab for values in ('a');
+create table mlparted5_b (d int, b int, c text, a int);
+alter table mlparted5_ab attach partition mlparted5_b for values in ('b');
+truncate mlparted;
+insert into mlparted values (1, 2, 'a', 1);
+insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
+insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
+select tableoid::regclass, * from mlparted order by a, b, c, d;
+ tableoid | a | b | c | d
+-------------+---+----+---+---
+ mlparted11 | 1 | 2 | a | 1
+ mlparted5_a | 1 | 40 | a | 1
+ mlparted5_b | 1 | 45 | b | 1
+(3 rows)
+
+alter table mlparted drop d;
+truncate mlparted;
+-- Remove the before last attribute.
+alter table mlparted add e int, add d int;
+alter table mlparted drop e;
+insert into mlparted values (1, 2, 'a', 1);
+insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
+insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
+select tableoid::regclass, * from mlparted order by a, b, c, d;
+ tableoid | a | b | c | d
+-------------+---+----+---+---
+ mlparted11 | 1 | 2 | a | 1
+ mlparted5_a | 1 | 40 | a | 1
+ mlparted5_b | 1 | 45 | b | 1
+(3 rows)
+
+alter table mlparted drop d;
+drop table mlparted5;
-- check that message shown after failure to find a partition shows the
-- appropriate key description (or none) in various situations
create table key_desc (a int, b int) partition by list ((a+0));
diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql
index a7f659bc2b4..4d1c92a54df 100644
--- a/src/test/regress/sql/insert.sql
+++ b/src/test/regress/sql/insert.sql
@@ -401,6 +401,34 @@ insert into mlparted values (70, 100);
select tableoid::regclass, * from mlparted_def;
+-- Check multi-level tuple routing with attributes dropped from the
+-- top-most parent. First remove the last attribute.
+alter table mlparted add d int, add e int;
+alter table mlparted drop e;
+create table mlparted5 partition of mlparted
+ for values from (1, 40) to (1, 50) partition by range (c);
+create table mlparted5_ab partition of mlparted5
+ for values from ('a') to ('c') partition by list (c);
+create table mlparted5_a partition of mlparted5_ab for values in ('a');
+create table mlparted5_b (d int, b int, c text, a int);
+alter table mlparted5_ab attach partition mlparted5_b for values in ('b');
+truncate mlparted;
+insert into mlparted values (1, 2, 'a', 1);
+insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
+insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
+select tableoid::regclass, * from mlparted order by a, b, c, d;
+alter table mlparted drop d;
+truncate mlparted;
+-- Remove the before last attribute.
+alter table mlparted add e int, add d int;
+alter table mlparted drop e;
+insert into mlparted values (1, 2, 'a', 1);
+insert into mlparted values (1, 40, 'a', 1); -- goes to mlparted5_a
+insert into mlparted values (1, 45, 'b', 1); -- goes to mlparted5_b
+select tableoid::regclass, * from mlparted order by a, b, c, d;
+alter table mlparted drop d;
+drop table mlparted5;
+
-- check that message shown after failure to find a partition shows the
-- appropriate key description (or none) in various situations
create table key_desc (a int, b int) partition by list ((a+0));