From: drh Date: Tue, 10 Apr 2007 18:17:55 +0000 (+0000) Subject: Preliminary fix for ticket #2291. This fixes the immediate problem. But X-Git-Tag: version-3.6.10~2335 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f33c9fad3521d992ae2a473c739e16ccf6403441;p=thirdparty%2Fsqlite.git Preliminary fix for ticket #2291. This fixes the immediate problem. But 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 --- 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