]> granicus.if.org Git - postgresql/commitdiff
Fix incorrect index behavior in COPY FROM with partitioned tables
authorDavid Rowley <drowley@postgresql.org>
Wed, 5 Jun 2019 06:28:38 +0000 (18:28 +1200)
committerDavid Rowley <drowley@postgresql.org>
Wed, 5 Jun 2019 06:28:38 +0000 (18:28 +1200)
86b85044e rewrote how COPY FROM works to allow multiple tuple buffers to
exist to once thus allowing multi-inserts to be used in more cases with
partitioned tables.  That commit neglected to update the estate's
es_result_relation_info when flushing the insert buffer to the partition
making it possible for the index tuples to be added into an index on the
wrong partition.

Fix this and also add an Assert in ExecInsertIndexTuples to help ensure
that we never make this mistake again.

Reported-by: Haruka Takatsuka
Author: Ashutosh Sharma
Discussion: https://postgr.es/m/15832-b1bf336a4ee246b5@postgresql.org

src/backend/commands/copy.c
src/backend/executor/execIndexing.c
src/test/regress/input/copy.source
src/test/regress/output/copy.source

index eca0be1ff96d7fff14f14378506a2a32290b58f5..2593732c16e11d4cb55416df46c26d553cdb1418 100644 (file)
@@ -2446,6 +2446,9 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
        ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
        TupleTableSlot **slots = buffer->slots;
 
+       /* Set es_result_relation_info to the ResultRelInfo we're flushing. */
+       estate->es_result_relation_info = resultRelInfo;
+
        /*
         * Print error context information correctly, if one of the operations
         * below fail.
index c41c5f45e7e55435bd3df6781a6e51310bd39b9b..40bd8049f05ee25ef47c7b70b1cabf83e523e79c 100644 (file)
@@ -299,6 +299,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
        indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
        heapRelation = resultRelInfo->ri_RelationDesc;
 
+       /* Sanity check: slot must belong to the same rel as the resultRelInfo. */
+       Assert(slot->tts_tableOid == RelationGetRelid(heapRelation));
+
        /*
         * We will use the EState's per-tuple context for evaluating predicates
         * and index expressions (creating it if it's not already there).
index aefc99167afeaa42bff30658d236243df194a20c..a1d529ad367d2199744b6e1d5d203bb3d3ac3265 100644 (file)
@@ -187,4 +187,17 @@ copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
 select tableoid::regclass,count(*),sum(a) from parted_copytest
 group by tableoid order by tableoid::regclass::name;
 
+truncate table parted_copytest;
+create index on parted_copytest (b);
+drop trigger part_ins_trig on parted_copytest_a2;
+
+copy parted_copytest from stdin;
+1      1       str1
+2      2       str2
+\.
+
+-- Ensure index entries were properly added during the copy.
+select * from parted_copytest where b = 1;
+select * from parted_copytest where b = 2;
+
 drop table parted_copytest;
index cf716aeccaa8b2f83d0c664e6ee9f9d8bf88c372..938d3551da26e25c8ec57153a604cc113d4a6678 100644 (file)
@@ -147,4 +147,21 @@ group by tableoid order by tableoid::regclass::name;
  parted_copytest_a2 |    10 |  10055
 (2 rows)
 
+truncate table parted_copytest;
+create index on parted_copytest (b);
+drop trigger part_ins_trig on parted_copytest_a2;
+copy parted_copytest from stdin;
+-- Ensure index entries were properly added during the copy.
+select * from parted_copytest where b = 1;
+ a | b |  c   
+---+---+------
+ 1 | 1 | str1
+(1 row)
+
+select * from parted_copytest where b = 2;
+ a | b |  c   
+---+---+------
+ 2 | 2 | str2
+(1 row)
+
 drop table parted_copytest;