diff --git a/manifest b/manifest index 5d0a75fd6f..06f45be099 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Comment\schanges\sin\sselect.c.\s(CVS\s4691) -D 2008-01-07T10:16:41 +C Registerify\sthe\sAUTOINCREMENT\sprocessing\sand\sthe\sOP_IsNull\sand\sOP_NotNull\noperators.\s(CVS\s4692) +D 2008-01-07T19:20:25 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -92,11 +92,11 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/delete.c 09c7b312a061d08df8a95b1f75cb10c6af14114a F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 99efbe91c16bc8a8dde1bb2d208a1246c07180d6 +F src/expr.c f84b4901dff3bacd08ece3f0de09318a5a298121 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 -F src/insert.c 20325a8c7cde8148859d58f0516f749a67f854ea +F src/insert.c 9c1a6501d79c9c4e674e0e2c3bc4a5207f9b3b95 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 @@ -127,11 +127,11 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1 -F src/pragma.c dfb200ec383b5ab3e81cd7bc4e1305e71053ef9a +F src/pragma.c ebf841efccc8d2df410fc10aa556a64256457ab4 F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c 31faeb619940082085e75f4cbef3f44c5e0f12d5 +F src/select.c 1162f736dbe227a1978f2d2c0e3fc111288f9653 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f @@ -168,7 +168,7 @@ F src/update.c 38e9e4c27896df2d189927e3b483cadf5641f47c F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c d30764669b30ca901993fa8f5854e4b3d021d25c +F src/vdbe.c 3d849013558e52b2c85134fc6ed655d6dc00ace7 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c @@ -177,7 +177,7 @@ F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a -F src/where.c 0d72b6431c23da6fb1b72422e364ac8fe7eb1d3a +F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba @@ -443,7 +443,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455 F test/tableapi.test 92651a95c23cf955e92407928e640536402fa3cc F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 -F test/tester.tcl 191b1b06da24f2bff246495d727f1b35798e8e48 +F test/tester.tcl ac4dace5f901b1ba5586b209f533f115d423985c F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7 F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 @@ -604,7 +604,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 8201f71729c3afbb41764cea3cda65b03150cb0c -R e1386487a1716925644579ddb593d24b -U danielk1977 -Z f79dec53250d0fbc0e2807bb20650e3c +P 38020592f15c072e0d221ae2e0df13508ac4bd49 +R dde2d5dbca593f8bc201758cd5d40a3d +U drh +Z 07f47472df3751ae71471b817e3e70f7 diff --git a/manifest.uuid b/manifest.uuid index e1ed53647b..8eebc9f5c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -38020592f15c072e0d221ae2e0df13508ac4bd49 \ No newline at end of file +aa48867cfa04da265b906e5b583bc7ac6b6a1157 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 41d4fccd2b..d332e4f866 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.335 2008/01/06 00:25:22 drh Exp $ +** $Id: expr.c,v 1.336 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -2134,14 +2134,14 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ } case TK_ISNULL: case TK_NOTNULL: { - int dest; + int addr; assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); sqlite3ExprCode(pParse, pExpr->pLeft, 0); - dest = sqlite3VdbeCurrentAddr(v) + 2; - sqlite3VdbeAddOp2(v, op, 1, dest); + addr = sqlite3VdbeAddOp0(v, op); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); + sqlite3VdbeJumpHere(v, addr); stackChng = 0; inReg = target; break; @@ -2222,11 +2222,10 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ break; } case TK_IN: { - int addr; + int j1, j2, j3, j4, j5; char affinity; int ckOffset = pParse->ckOffset; int eType; - int iLabel = sqlite3VdbeMakeLabel(v); eType = sqlite3FindInIndex(pParse, pExpr, 0); @@ -2243,24 +2242,25 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ ** pExpr->iTable contains the values that make up the (...) set. */ sqlite3ExprCode(pParse, pExpr->pLeft, 0); - addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+4); /* addr + 0 */ + sqlite3VdbeAddOp0(v, OP_SCopy); + j1 = sqlite3VdbeAddOp0(v, OP_NotNull); sqlite3VdbeAddOp1(v, OP_Pop, 2); sqlite3VdbeAddOp0(v, OP_Null); - sqlite3VdbeAddOp2(v, OP_Goto, 0, iLabel); + j2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j1); if( eType==IN_INDEX_ROWID ){ - int iAddr = sqlite3VdbeCurrentAddr(v)+3; - sqlite3VdbeAddOp2(v, OP_MustBeInt, 1, iAddr); - sqlite3VdbeAddOp2(v, OP_NotExists, pExpr->iTable, iAddr); - sqlite3VdbeAddOp2(v, OP_Goto, pExpr->iTable, iLabel); + j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, 1); + j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable); + j5 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j3); + sqlite3VdbeJumpHere(v, j4); }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, - &affinity, 1); /* addr + 4 */ - sqlite3VdbeAddOp2(v, OP_Found, pExpr->iTable, iLabel); + sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &affinity, 1); + j5 = sqlite3VdbeAddOp1(v, OP_Found, pExpr->iTable); } - sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1); /* addr + 6 */ - sqlite3VdbeResolveLabel(v, iLabel); - + sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j5); break; } #endif @@ -2485,7 +2485,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3ExprCode(pParse, pExpr->pLeft, 0); - sqlite3VdbeAddOp2(v, op, 1, dest); + sqlite3VdbeAddOp2(v, op, 0, dest); break; } case TK_BETWEEN: { @@ -2597,7 +2597,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_ISNULL: case TK_NOTNULL: { sqlite3ExprCode(pParse, pExpr->pLeft, 0); - sqlite3VdbeAddOp2(v, op, 1, dest); + sqlite3VdbeAddOp2(v, op, 0, dest); break; } case TK_BETWEEN: { diff --git a/src/insert.c b/src/insert.c index c0ef2aeef4..c4fe10717c 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.214 2008/01/06 00:25:22 drh Exp $ +** $Id: insert.c,v 1.215 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" @@ -138,44 +138,46 @@ static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ /* ** Write out code to initialize the autoincrement logic. This code ** looks up the current autoincrement value in the sqlite_sequence -** table and stores that value in a memory cell. Code generated by -** autoIncStep() will keep that memory cell holding the largest +** table and stores that value in a register. Code generated by +** autoIncStep() will keep that register holding the largest ** rowid value. Code generated by autoIncEnd() will write the new ** largest value of the counter back into the sqlite_sequence table. ** ** This routine returns the index of the mem[] cell that contains ** the maximum rowid counter. ** -** Two memory cells are allocated. The next memory cell befor the -** one returned holds the rowid in sqlite_sequence where we will -** write back the revised maximum rowid. +** Three consecutive registers are allocated by this routine. The +** first two hold the name of the target table and the maximum rowid +** inserted into the target table, respectively. +** The third holds the rowid in sqlite_sequence where we will +** write back the revised maximum rowid. This routine returns the +** index of the second of these three registers. */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ - int memId = 0; + int memId = 0; /* Register holding maximum rowid */ if( pTab->autoInc ){ Vdbe *v = pParse->pVdbe; Db *pDb = &pParse->db->aDb[iDb]; int iCur = pParse->nTab; - int addr; + int addr; /* Address of the top of the loop */ assert( v ); - addr = sqlite3VdbeCurrentAddr(v); - pParse->nMem += 2; - memId = pParse->nMem; + pParse->nMem++; /* Holds name of table */ + memId = ++pParse->nMem; + pParse->nMem++; sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+12); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8); sqlite3VdbeAddOp2(v, OP_Column, iCur, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0); - sqlite3VdbeAddOp2(v, OP_Move, 0, memId-1); - sqlite3VdbeAddOp2(v, OP_Column, iCur, 1); - sqlite3VdbeAddOp2(v, OP_Move, 0, memId); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12); - sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3); + sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+7); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8); + sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); } return memId; @@ -189,15 +191,15 @@ static int autoIncBegin( ** larger than the maximum rowid in the memId memory cell, then the ** memory cell is updated. The stack is unchanged. */ -static void autoIncStep(Parse *pParse, int memId, int iRowid){ +static void autoIncStep(Parse *pParse, int memId, int regRowid){ if( memId>0 ){ - sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, iRowid); + sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); } } /* ** After doing one or more inserts, the maximum rowid is stored -** in mem[memId]. Generate code to write this value back into the +** in reg[memId]. Generate code to write this value back into the ** the sqlite_sequence table. */ static void autoIncEnd( @@ -210,19 +212,18 @@ static void autoIncEnd( int iCur = pParse->nTab; Vdbe *v = pParse->pVdbe; Db *pDb = &pParse->db->aDb[iDb]; - int addr; + int j1; + assert( v ); - addr = sqlite3VdbeCurrentAddr(v); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - sqlite3VdbeAddOp2(v, OP_SCopy, memId-1, 0); - sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6); - sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp1(v, OP_NewRowid, iCur); - sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_SCopy, memId, 0); - sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0); - sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND); - sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); + sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); + sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1); + sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1); + sqlite3VdbeChangeP5(v, -1, OPFLAG_APPEND); + sqlite3VdbeAddOp1(v, OP_Close, iCur); } } #else @@ -341,32 +342,38 @@ void sqlite3Insert( IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ){ - Table *pTab; /* The table to insert into */ + sqlite3 *db; /* The main database structure */ + Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ const char *zDb; /* Name of the database holding this table */ int i, j, idx; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ + int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ int base = 0; /* VDBE Cursor number for pTab */ - int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ - sqlite3 *db; /* The main database structure */ int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ int endOfLoop; /* Label for the end of the insertion loop */ int useTempTable = 0; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ + int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ int iSelectLoop = 0; /* Address of code that implements the SELECT */ int iCleanup = 0; /* Address of the cleanup code */ int iInsertBlock = 0; /* Address of the subroutine used to insert data */ - int iCntMem = 0; /* Memory cell used for the row counter */ - int iBaseReg; /* Base register for data */ - int newIdx = -1; /* Cursor for the NEW table */ + int newIdx = -1; /* Cursor for the NEW pseudo-table */ + int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ - int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ int appendFlag = 0; /* True if the insert is likely to be an append */ - int iDb; - int nHidden = 0; + /* Register allocations */ + int regFromSelect; /* Base register for data coming from SELECT */ + int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ + int regRowCount = 0; /* Memory cell used for the row counter */ + int regIns; /* Block of regs holding rowid+data being inserted */ + int regRowid; /* registers holding insert rowid */ + int regData; /* register holding first column to insert */ + int regRecord; /* Holds the assemblied row record */ + #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ @@ -455,11 +462,9 @@ void sqlite3Insert( #endif /* SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the - ** sqlite_sequence table and store it in memory cell counterMem. Also - ** remember the rowid of the sqlite_sequence table entry in memory cell - ** counterRowid. + ** sqlite_sequence table and store it in memory cell regAutoinc. */ - counterMem = autoIncBegin(pParse, iDb, pTab); + regAutoinc = autoIncBegin(pParse, iDb, pTab); /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then this step also generates @@ -486,7 +491,7 @@ void sqlite3Insert( goto insert_cleanup; } - iBaseReg = dest.iMem; + regFromSelect = dest.iMem; iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); @@ -510,7 +515,7 @@ void sqlite3Insert( */ srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); - sqlite3VdbeAddOp2(v, OP_RegMakeRec, iBaseReg, nColumn); + sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn); sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND); @@ -620,8 +625,8 @@ void sqlite3Insert( /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ - iCntMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, iCntMem); + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ @@ -642,10 +647,22 @@ void sqlite3Insert( }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iInsertBlock); - sqlite3RegToStack(pParse, iBaseReg, nColumn); + sqlite3RegToStack(pParse, regFromSelect, nColumn); sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); } + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assemblied row record. + */ + regRecord = ++pParse->nMem; + regRowid = regIns = pParse->nMem+1; + pParse->nMem += pTab->nCol + 1; + if( IsVirtual(pTab) ){ + regRowid++; + pParse->nMem++; + } + regData = regRowid+1; + /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); @@ -662,12 +679,15 @@ void sqlite3Insert( }else if( useTempTable ){ sqlite3VdbeAddOp2(v, OP_Column, srcTab, keyColumn); }else{ + int j1; assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); - sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp2(v, OP_Integer, -1, 0); - sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); + sqlite3VdbeAddOp0(v, OP_SCopy); + j1 = sqlite3VdbeAddOp0(v, OP_NotNull); + sqlite3VdbeAddOp1(v, OP_Pop, 1); + sqlite3VdbeAddOp1(v, OP_Integer, -1); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp0(v, OP_MustBeInt); } /* Cannot have triggers on a virtual table. If it were possible, @@ -719,19 +739,15 @@ void sqlite3Insert( ** case the record number is the same as that column. */ if( !isView ){ - int iReg = pParse->nMem+1; - int iRowid = iReg+(IsVirtual(pTab)?1:0); - pParse->nMem += pTab->nCol + (IsVirtual(pTab)?2:1); - if( IsVirtual(pTab) ){ /* The row that the VUpdate opcode will delete: none */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); + sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); } if( keyColumn>=0 ){ if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid); + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), iRowid); + sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); @@ -740,36 +756,36 @@ void sqlite3Insert( appendFlag = 1; pOp->opcode = OP_NewRowid; pOp->p1 = base; - pOp->p2 = iRowid; - pOp->p3 = counterMem; + pOp->p2 = regRowid; + pOp->p3 = regAutoinc; }else{ /* TODO: Avoid this use of the stack. */ - sqlite3VdbeAddOp2(v, OP_Move, 0, iRowid); + sqlite3VdbeAddOp2(v, OP_Move, 0, regRowid); } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ if( !appendFlag ){ - sqlite3VdbeAddOp2(v, OP_IfMemNull, iRowid, sqlite3VdbeCurrentAddr(v)+2); + sqlite3VdbeAddOp2(v, OP_IfMemNull, regRowid, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem); - sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, iRowid); + sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc); + sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regRowid); } }else if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid); + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); }else{ - sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem); + sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc); appendFlag = 1; } - autoIncStep(pParse, counterMem, iRowid); + autoIncStep(pParse, regAutoinc, regRowid); /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ nHidden = 0; for(i=0; inCol; i++){ - int iRegStore = iRowid+1+i; + int iRegStore = regRowid+1+i; if( i==pTab->iPKey ){ /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the record number will be substituted @@ -808,12 +824,12 @@ void sqlite3Insert( #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ pParse->pVirtualLock = pTab; - sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, iReg, + sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, (const char*)pTab->pVtab, P4_VTAB); }else #endif { - sqlite3RegToStack(pParse, iReg, pTab->nCol+1); + sqlite3RegToStack(pParse, regIns, pTab->nCol+1); sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, @@ -825,7 +841,7 @@ void sqlite3Insert( /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, iCntMem, 1); + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( triggers_exist ){ @@ -858,10 +874,10 @@ void sqlite3Insert( } /* Update the sqlite_sequence table by storing the content of the - ** counter value in memory counterMem back into the sqlite_sequence + ** counter value in memory regAutoinc back into the sqlite_sequence ** table. */ - autoIncEnd(pParse, iDb, pTab, counterMem); + autoIncEnd(pParse, iDb, pTab, regAutoinc); /* ** Return the number of rows inserted. If this routine is @@ -869,7 +885,7 @@ void sqlite3Insert( ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, iCntMem, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC); } @@ -882,14 +898,14 @@ insert_cleanup: } /* -** Generate code to do a constraint check prior to an INSERT or an UPDATE. +** Generate code to do constraint checks prior to an INSERT or an UPDATE. ** ** When this routine is called, the stack contains (from bottom to top) ** the following values: ** ** 1. The rowid of the row to be updated before the update. This ** value is omitted unless we are doing an UPDATE that involves a -** change to the record number. +** change to the record number. (Or writing to a virtual table.) ** ** 2. The rowid of the row after the update. ** @@ -1004,7 +1020,7 @@ void sqlite3GenerateConstraintChecks( onError = OE_Abort; } sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i)); - addr = sqlite3VdbeAddOp2(v, OP_NotNull, 1, 0); + addr = sqlite3VdbeAddOp0(v, OP_NotNull); assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ @@ -1413,7 +1429,7 @@ static int xferOptimization( int emptySrcTest; /* Address of test for empty pSrc */ Vdbe *v; /* The VDBE we are building */ KeyInfo *pKey; /* Key information for an index */ - int counterMem; /* Memory register used by AUTOINC */ + int regAutoinc; /* Memory register used by AUTOINC */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ if( pSelect==0 ){ @@ -1541,7 +1557,7 @@ static int xferOptimization( sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; - counterMem = autoIncBegin(pParse, iDbDest, pDest); + regAutoinc = autoIncBegin(pParse, iDbDest, pDest); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ /* If tables do not have an INTEGER PRIMARY KEY and there @@ -1569,7 +1585,7 @@ static int xferOptimization( sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); - autoIncStep(pParse, counterMem, 0); + autoIncStep(pParse, regAutoinc, 0); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest); }else{ @@ -1580,7 +1596,7 @@ static int xferOptimization( sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); - autoIncEnd(pParse, iDbDest, pDest, counterMem); + autoIncEnd(pParse, iDbDest, pDest, regAutoinc); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; diff --git a/src/pragma.c b/src/pragma.c index 50e3f9c8ff..b4b4059161 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.161 2008/01/05 16:29:28 drh Exp $ +** $Id: pragma.c,v 1.162 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -882,7 +882,7 @@ void sqlite3Pragma( } if( cnt==0 ) continue; sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i); - addr = sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0); + addr = sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); diff --git a/src/select.c b/src/select.c index e818218e84..4e39192d64 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.391 2008/01/07 10:16:41 danielk1977 Exp $ +** $Id: select.c,v 1.392 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" @@ -809,12 +809,16 @@ static void generateSortTail( } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { + int j1, j2; assert( nColumn==1 ); - sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp0(v, OP_SCopy); + j1 = sqlite3VdbeAddOp0(v, OP_NotNull); + sqlite3VdbeAddOp1(v, OP_Pop, 1); + j2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); + sqlite3VdbeJumpHere(v, j2); break; } case SRT_Mem: { diff --git a/src/vdbe.c b/src/vdbe.c index a8643d957e..58b1b1454f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.686 2008/01/06 00:25:22 drh Exp $ +** $Id: vdbe.c,v 1.687 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -2110,7 +2110,7 @@ case OP_IfNot: { /* no-push, jump */ break; } -/* Opcode: IsNull P1 P2 * +/* Opcode: StackIsNull P1 P2 * ** ** Check the top of the stack and jump to P2 if the top of the stack ** is NULL. If P1 is positive, then pop P1 elements from the stack @@ -2118,7 +2118,7 @@ case OP_IfNot: { /* no-push, jump */ ** pop -P1 elements from the stack only if the jump is taken and leave ** the stack unchanged if the jump is not taken. */ -case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */ +case OP_StackIsNull: { /* no-push, jump */ if( pTos->flags & MEM_Null ){ pc = pOp->p2-1; if( pOp->p1<0 ){ @@ -2131,40 +2131,31 @@ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */ break; } -/* Opcode: AnyNull P1 P2 P3 * * +/* Opcode: IsNull P1 P2 * ** -** Check P3 registers beginning with P1. If any are NULL then jump -** to P2. +** Jump to P2 if the value in register P1 is NULL. +** +** If P1 is 0 then use the top of the stack instead of a register +** and pop the stack regardless of whether or not the jump is taken. */ -case OP_AnyNull: { /* no-push, jump, in1 */ - int n = pOp->p3; - assert( n>0 && pOp->p1+n<=p->nMem ); - while( n>0 ){ - if( pIn1->flags & MEM_Null ){ - pc = pOp->p2-1; - break; - } - n--; - pIn1++; +case OP_IsNull: { /* same as TK_ISNULL, no-push, jump, in1 */ + if( (pIn1->flags & MEM_Null)!=0 ){ + pc = pOp->p2 - 1; } break; } /* Opcode: NotNull P1 P2 * ** -** Jump to P2 if the top abs(P1) values on the stack are all not NULL. -** Regardless of whether or not the jump is taken, pop the stack -** P1 times if P1 is greater than zero. But if P1 is negative, -** leave the stack unchanged. +** Jump to P2 if the value in register P1 is not NULL. +** +** If P1 is 0 then use the top of the stack instead of a register +** and pop the stack regardless of whether or not the jump is taken. */ -case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump */ - int i, cnt; - cnt = pOp->p1; - if( cnt<0 ) cnt = -cnt; - assert( &pTos[1-cnt] >= p->aStack ); - for(i=0; i=cnt ) pc = pOp->p2-1; - if( pOp->p1>0 ) popStack(&pTos, cnt); +case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump, in1 */ + if( (pIn1->flags & MEM_Null)==0 ){ + pc = pOp->p2 - 1; + } break; } diff --git a/src/where.c b/src/where.c index 360e191ee4..4d9454fbbc 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.276 2008/01/05 17:39:30 danielk1977 Exp $ +** $Id: where.c,v 1.277 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" @@ -1757,7 +1757,7 @@ static void codeEqualityTerm( pIn += pLevel->nIn - 1; pIn->iCur = iTab; pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0); - sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0); + sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0); }else{ pLevel->nIn = 0; } @@ -1824,7 +1824,7 @@ static void codeAllEqualityTerms( assert( (pTerm->flags & TERM_CODED)==0 ); codeEqualityTerm(pParse, pTerm, pLevel); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ - sqlite3VdbeAddOp2(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk); + sqlite3VdbeAddOp2(v, OP_StackIsNull, termsInMem ? -1 : -(j+1), pLevel->brk); } if( termsInMem ){ sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1); @@ -2467,7 +2467,7 @@ WhereInfo *sqlite3WhereBegin( pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); - sqlite3VdbeAddOp2(v, OP_IsNull, -(nEq*2+1), nxt); + sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq*2+1), nxt); topEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); testOp = OP_IdxGE; @@ -2511,7 +2511,7 @@ WhereInfo *sqlite3WhereBegin( pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); - sqlite3VdbeAddOp2(v, OP_IsNull, -(nEq+1), nxt); + sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq+1), nxt); btmEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); }else{ @@ -2553,7 +2553,7 @@ WhereInfo *sqlite3WhereBegin( } if( topLimit | btmLimit ){ sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq); - sqlite3VdbeAddOp2(v, OP_IsNull, 1, cont); + sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont); } if( !omitTable ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0); diff --git a/test/tester.tcl b/test/tester.tcl index 9082e811be..c377fa155e 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,7 +11,7 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.95 2008/01/04 19:10:29 danielk1977 Exp $ +# $Id: tester.tcl,v 1.96 2008/01/07 19:20:25 drh Exp $ set tcl_precision 15 @@ -51,6 +51,20 @@ for {set i 0} {$i<[llength $argv]} {incr i} { } } +# +# Check the command-line arguments to set the maximum number of +# errors tolerated before halting. +# +if {![info exists maxErr]} { + set maxErr 1000 +} +for {set i 0} {$i<[llength $argv]} {incr i} { + if {[regexp {^--maxerror=(\d+)$} [lindex $argv $i] all maxErr]} { + set argv [lreplace $argv $i $i] + } +} +#puts "Max error = $maxErr" + # Use the pager codec if it is available # @@ -86,7 +100,6 @@ set nErr 0 set nTest 0 set skip_test 0 set failList {} -set maxErr 1000 if {![info exists speedTest]} { set speedTest 0 }