diff --git a/manifest b/manifest index 8258689acf..6babc0b5dc 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index d44b8975fc..b17d2b2ad8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e14374e4e6f14a90ecb53c2e7c86908a220c6d68 \ No newline at end of file +34fec312fd1aeabb04e07d6aa061991775c7b8a1 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 34f87432dc..e1864ad929 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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); diff --git a/test/insert4.test b/test/insert4.test index 56e23da16a..e8b3f3624e 100644 --- a/test/insert4.test +++ b/test/insert4.test @@ -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