]> granicus.if.org Git - postgresql/commitdiff
Set ecxt_scantuple correctly for tuple routing.
authorRobert Haas <rhaas@postgresql.org>
Tue, 24 Jan 2017 20:34:39 +0000 (15:34 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 24 Jan 2017 20:34:39 +0000 (15:34 -0500)
In 2ac3ef7a01df859c62d0a02333b646d65eaec5ff, we changed things so that
it's possible for a different TupleTableSlot to be used for partitioned
tables at successively lower levels.  If we do end up changing the slot
from the original, we must update ecxt_scantuple to point to the new one
for partition key of the tuple to be computed correctly.

Reported by Rajkumar Raghuwanshi.  Patch by Amit Langote.

Discussion: http://postgr.es/m/CAKcux6%3Dm1qyqB2k6cjniuMMrYXb75O-MB4qGQMu8zg-iGGLjDw%40mail.gmail.com

src/backend/catalog/partition.c
src/backend/executor/execMain.c
src/test/regress/expected/insert.out
src/test/regress/sql/insert.sql

index e5af283997f8458dd8cc454805ea7efcfe458a2c..7be60529c5369d29b4bb0b5beaa4efd3886afdf7 100644 (file)
@@ -1679,7 +1679,10 @@ get_partition_for_tuple(PartitionDispatch *pd,
        bool            isnull[PARTITION_MAX_KEYS];
        int                     cur_offset,
                                cur_index;
-       int                     i;
+       int                     i,
+                               result;
+       ExprContext *ecxt = GetPerTupleExprContext(estate);
+       TupleTableSlot *ecxt_scantuple_old = ecxt->ecxt_scantuple;
 
        /* start with the root partitioned table */
        parent = pd[0];
@@ -1708,7 +1711,15 @@ get_partition_for_tuple(PartitionDispatch *pd,
                        slot = myslot;
                }
 
-               /* Extract partition key from tuple */
+               /*
+                * Extract partition key from tuple. Expression evaluation machinery
+                * that FormPartitionKeyDatum() invokes expects ecxt_scantuple to
+                * point to the correct tuple slot.  The slot might have changed from
+                * what was used for the parent table if the table of the current
+                * partitioning level has different tuple descriptor from the parent.
+                * So update ecxt_scantuple accordingly.
+                */
+               ecxt->ecxt_scantuple = slot;
                FormPartitionKeyDatum(parent, slot, estate, values, isnull);
 
                if (key->strategy == PARTITION_STRATEGY_RANGE)
@@ -1763,16 +1774,21 @@ get_partition_for_tuple(PartitionDispatch *pd,
                 */
                if (cur_index < 0)
                {
+                       result = -1;
                        *failed_at = RelationGetRelid(parent->reldesc);
-                       return -1;
+                       break;
                }
-               else if (parent->indexes[cur_index] < 0)
-                       parent = pd[-parent->indexes[cur_index]];
-               else
+               else if (parent->indexes[cur_index] >= 0)
+               {
+                       result = parent->indexes[cur_index];
                        break;
+               }
+               else
+                       parent = pd[-parent->indexes[cur_index]];
        }
 
-       return parent->indexes[cur_index];
+       ecxt->ecxt_scantuple = ecxt_scantuple_old;
+       return result;
 }
 
 /*
index 4e8493ec141be0f83ae0e52255bc2b550d9a90a6..3a5b5b21265cf36db784c8741a3a200d6f8d0d1d 100644 (file)
@@ -3192,9 +3192,7 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
 {
        int                     result;
        Oid                     failed_at;
-       ExprContext *econtext = GetPerTupleExprContext(estate);
 
-       econtext->ecxt_scantuple = slot;
        result = get_partition_for_tuple(pd, slot, estate, &failed_at);
        if (result < 0)
        {
index 538fe5b1819e9b89a7bc6b0d5edb1dce14cb711d..81af3ef4972afa1a5ce0aa26135b3ce302817495 100644 (file)
@@ -320,7 +320,7 @@ drop table part_ee_ff, part_gg2_2, part_gg2_1, part_gg2, part_gg1, part_gg;
 drop table part_aa_bb, part_cc_dd, part_null, list_parted;
 -- more tests for certain multi-level partitioning scenarios
 create table p (a int, b int) partition by range (a, b);
-create table p1 (b int, a int not null) partition by range (b);
+create table p1 (b int not null, a int not null) partition by range ((b+0));
 create table p11 (like p1);
 alter table p11 drop a;
 alter table p11 add a int;
index 3d5138a8e0704ab98d180d78a171e8908fb248f5..454e1ce2e78a51ade614941025ddb8ef08b13f20 100644 (file)
@@ -193,7 +193,7 @@ drop table part_aa_bb, part_cc_dd, part_null, list_parted;
 
 -- more tests for certain multi-level partitioning scenarios
 create table p (a int, b int) partition by range (a, b);
-create table p1 (b int, a int not null) partition by range (b);
+create table p1 (b int not null, a int not null) partition by range ((b+0));
 create table p11 (like p1);
 alter table p11 drop a;
 alter table p11 add a int;