]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Preliminary fix for ticket #2291. This fixes the immediate problem. But
authordrh <drh@noemail.net>
Tue, 10 Apr 2007 18:17:55 +0000 (18:17 +0000)
committerdrh <drh@noemail.net>
Tue, 10 Apr 2007 18:17:55 +0000 (18:17 +0000)
we really need to write more tests for the xfer optimization in order to
look for other related problems before closing this ticket. (CVS 3835)

FossilOrigin-Name: 34fec312fd1aeabb04e07d6aa061991775c7b8a1

manifest
manifest.uuid
src/insert.c
test/insert4.test

index 8258689acfed4a18ede1e3867fac7d461a2cc937..6babc0b5dcf35a30c1cd1b0a4c52f3a7715ac09b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Be\scareful\snot\sto\suse\sthe\sresult\sof\ssqlite3_value_blob()\safter\schanging\nthe\srepresentation\sof\san\sobject.\s\sTicket\s#2290.\s(CVS\s3834)
-D 2007-04-10T13:51:18
+C Preliminary\sfix\sfor\sticket\s#2291.\s\sThis\sfixes\sthe\simmediate\sproblem.\s\sBut\nwe\sreally\sneed\sto\swrite\smore\stests\sfor\sthe\sxfer\soptimization\sin\sorder\sto\nlook\sfor\sother\srelated\sproblems\sbefore\sclosing\sthis\sticket.\s(CVS\s3835)
+D 2007-04-10T18:17:55
 F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -70,7 +70,7 @@ F src/expr.c a8740c24af3f39f2d502be1a1c640c96435eaac0
 F src/func.c 007d957c057bb42b0d37aa6ad4be0e1c67a8871b
 F src/hash.c 67b23e14f0257b69a3e8aa663e4eeadc1a2b6fd5
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
-F src/insert.c 967be8c143d64c904ba4e6f66760824898a75e3c
+F src/insert.c f3cd178575bd2a4b65a9a1313f391e1f78221ca3
 F src/legacy.c 2631df6a861f830d6b1c0fe92b9fdd745b2c0cd6
 F src/loadext.c 146fb9b9dc6133e763888d710205c32ebf8eeca2
 F src/main.c c8915777ae8e50823d01eefe2b674ef68c32bf61
@@ -243,7 +243,7 @@ F test/index3.test f66718cd92ce1216819d47e6a156755e4b2c4ca1
 F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
 F test/insert2.test 5a20e1ace5fa0800b58d28284212290189b49aed
 F test/insert3.test 09a532d5b6f3a788d91be0d4d368462f522685d1
-F test/insert4.test 0bb119fea2868afdcf78e4e3e3bfed27bbdb2430
+F test/insert4.test c5af4d3d123329aa13e8b4fb265a2f143a43d0cd
 F test/interrupt.test c38b7f7c17914f0cd6a119beed5d03bc3f47f9eb
 F test/intpkey.test af4fd826c4784ec5c93b444de07adea0254d0d30
 F test/ioerr.test 491d42c49bbec598966d26b01ed7901f55e5ee2d
@@ -457,7 +457,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 81be7290a4db7b74a533aaf95c7389eb4bde6a88
-R 2b4707c8870f2a324132e4edcdf8905d
+P e14374e4e6f14a90ecb53c2e7c86908a220c6d68
+R f289180cefc2c2db5021e660d1bbcc38
 U drh
-Z 24df7c4f8c69db5a5c90263a033c10d0
+Z 390c704b66783e56774a93432326a3cd
index d44b8975fc4cb77dac19a6f9755353e224e774b1..b17d2b2ad8d9581b662ff113e98a788c5d79834b 100644 (file)
@@ -1 +1 @@
-e14374e4e6f14a90ecb53c2e7c86908a220c6d68
\ No newline at end of file
+34fec312fd1aeabb04e07d6aa061991775c7b8a1
\ No newline at end of file
index 34f87432dc98947fd5198b24d2ea0ee9c89ccda2..e1864ad92920c64e8c8cc28013b882887d788a63 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.183 2007/04/01 23:49:52 drh Exp $
+** $Id: insert.c,v 1.184 2007/04/10 18:17:55 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1374,10 +1374,10 @@ static int xferOptimization(
   int addr1, addr2;                /* Loop addresses */
   int emptyDestTest;               /* Address of test for empty pDest */
   int emptySrcTest;                /* Address of test for empty pSrc */
-  int memRowid = 0;                /* A memcell containing a rowid from pSrc */
   Vdbe *v;                         /* The VDBE we are building */
   KeyInfo *pKey;                   /* Key information for an index */
   int counterMem;                  /* Memory register used by AUTOINC */
+  int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
 
   if( pSelect==0 ){
     return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
@@ -1474,6 +1474,9 @@ static int xferOptimization(
     }
   }
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
+    if( pDestIdx->onError!=OE_None ){
+      destHasUniqueIdx = 1;
+    }
     for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
       if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
     }
@@ -1504,11 +1507,16 @@ static int xferOptimization(
   iDest = pParse->nTab++;
   counterMem = autoIncBegin(pParse, iDbDest, pDest);
   sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
-  if( pDest->iPKey<0 && pDest->pIndex!=0 ){
+  if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){
     /* If tables do not have an INTEGER PRIMARY KEY and there
     ** are indices to be copied and the destination is not empty,
     ** we have to disallow the transfer optimization because the
     ** the rowids might change which will mess up indexing.
+    **
+    ** Or if the destination has a UNIQUE index and is not empty,
+    ** we also disallow the transfer optimization because we cannot
+    ** insure that all entries in the union of DEST and SRC will be
+    ** unique.
     */
     addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0);
     emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
@@ -1518,11 +1526,6 @@ static int xferOptimization(
   }
   sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
   emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
-  if( pDest->pIndex!=0 ){
-    sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
-    memRowid = pParse->nMem++;
-    sqlite3VdbeAddOp(v, OP_MemStore, memRowid, pDest->iPKey>=0);
-  }
   if( pDest->iPKey>=0 ){
     addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
     sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -1562,13 +1565,6 @@ static int xferOptimization(
                    (char*)pKey, P3_KEYINFO_HANDOFF);
     addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
     sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0);
-    if( pDestIdx->onError!=OE_None ){
-      sqlite3VdbeAddOp(v, OP_MemLoad, memRowid, 0);
-      addr2 = sqlite3VdbeAddOp(v, OP_IsUnique, iDest, 0);
-      sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, 
-                    "UNIQUE constraint failed", P3_STATIC);
-      sqlite3VdbeJumpHere(v, addr2);
-    }
     sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1);
     sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1);
     sqlite3VdbeJumpHere(v, addr1);
index 56e23da16aa6401cfd30fb561cb965d95e9f019b..e8b3f3624efe00fcbac81d4c091dec016a514658 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the INSERT transfer optimization.
 #
-# $Id: insert4.test,v 1.3 2007/02/24 15:18:50 drh Exp $
+# $Id: insert4.test,v 1.4 2007/04/10 18:17:55 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -227,4 +227,16 @@ xfer_check insert4-3.22 1 {1 9} \
     {x integer, b int}
 
 
+# Ticket #2291.
+#
+do_test insert4-4.1 {
+  execsql {
+    CREATE TABLE t4(a, b, PRIMARY KEY(a,b));
+    INSERT INTO t4 VALUES(NULL,0);
+    INSERT INTO t4 VALUES(NULL,1);
+    INSERT INTO t4 VALUES(NULL,1);
+    VACUUM;   
+  }
+} {}
+
 finish_test