1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Registerify the AUTOINCREMENT processing and the OP_IsNull and OP_NotNull

operators. (CVS 4692)

FossilOrigin-Name: aa48867cfa04da265b906e5b583bc7ac6b6a1157
This commit is contained in:
drh
2008-01-07 19:20:24 +00:00
parent 738bdcfbf8
commit 6a288a33f9
9 changed files with 186 additions and 162 deletions

View File

@ -1,5 +1,5 @@
C Comment\schanges\sin\sselect.c.\s(CVS\s4691) C Registerify\sthe\sAUTOINCREMENT\sprocessing\sand\sthe\sOP_IsNull\sand\sOP_NotNull\noperators.\s(CVS\s4692)
D 2008-01-07T10:16:41 D 2008-01-07T19:20:25
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -92,11 +92,11 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
F src/delete.c 09c7b312a061d08df8a95b1f75cb10c6af14114a F src/delete.c 09c7b312a061d08df8a95b1f75cb10c6af14114a
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 99efbe91c16bc8a8dde1bb2d208a1246c07180d6 F src/expr.c f84b4901dff3bacd08ece3f0de09318a5a298121
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/insert.c 20325a8c7cde8148859d58f0516f749a67f854ea F src/insert.c 9c1a6501d79c9c4e674e0e2c3bc4a5207f9b3b95
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@ -127,11 +127,11 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429 F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429
F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1 F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1
F src/pragma.c dfb200ec383b5ab3e81cd7bc4e1305e71053ef9a F src/pragma.c ebf841efccc8d2df410fc10aa556a64256457ab4
F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
F src/select.c 31faeb619940082085e75f4cbef3f44c5e0f12d5 F src/select.c 1162f736dbe227a1978f2d2c0e3fc111288f9653
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
@ -168,7 +168,7 @@ F src/update.c 38e9e4c27896df2d189927e3b483cadf5641f47c
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
F src/vdbe.c d30764669b30ca901993fa8f5854e4b3d021d25c F src/vdbe.c 3d849013558e52b2c85134fc6ed655d6dc00ace7
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
@ -177,7 +177,7 @@ F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
F src/where.c 0d72b6431c23da6fb1b72422e364ac8fe7eb1d3a F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba
@ -443,7 +443,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455
F test/tableapi.test 92651a95c23cf955e92407928e640536402fa3cc F test/tableapi.test 92651a95c23cf955e92407928e640536402fa3cc
F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9 F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
F test/tester.tcl 191b1b06da24f2bff246495d727f1b35798e8e48 F test/tester.tcl ac4dace5f901b1ba5586b209f533f115d423985c
F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
@ -604,7 +604,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P 8201f71729c3afbb41764cea3cda65b03150cb0c P 38020592f15c072e0d221ae2e0df13508ac4bd49
R e1386487a1716925644579ddb593d24b R dde2d5dbca593f8bc201758cd5d40a3d
U danielk1977 U drh
Z f79dec53250d0fbc0e2807bb20650e3c Z 07f47472df3751ae71471b817e3e70f7

View File

@ -1 +1 @@
38020592f15c072e0d221ae2e0df13508ac4bd49 aa48867cfa04da265b906e5b583bc7ac6b6a1157

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite. ** 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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -2134,14 +2134,14 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
} }
case TK_ISNULL: case TK_ISNULL:
case TK_NOTNULL: { case TK_NOTNULL: {
int dest; int addr;
assert( TK_ISNULL==OP_IsNull ); assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull ); assert( TK_NOTNULL==OP_NotNull );
sqlite3VdbeAddOp2(v, OP_Integer, 1, target); sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pLeft, 0);
dest = sqlite3VdbeCurrentAddr(v) + 2; addr = sqlite3VdbeAddOp0(v, op);
sqlite3VdbeAddOp2(v, op, 1, dest);
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
sqlite3VdbeJumpHere(v, addr);
stackChng = 0; stackChng = 0;
inReg = target; inReg = target;
break; break;
@ -2222,11 +2222,10 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
break; break;
} }
case TK_IN: { case TK_IN: {
int addr; int j1, j2, j3, j4, j5;
char affinity; char affinity;
int ckOffset = pParse->ckOffset; int ckOffset = pParse->ckOffset;
int eType; int eType;
int iLabel = sqlite3VdbeMakeLabel(v);
eType = sqlite3FindInIndex(pParse, pExpr, 0); 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. ** pExpr->iTable contains the values that make up the (...) set.
*/ */
sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pLeft, 0);
addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp0(v, OP_SCopy);
sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+4); /* addr + 0 */ j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
sqlite3VdbeAddOp1(v, OP_Pop, 2); sqlite3VdbeAddOp1(v, OP_Pop, 2);
sqlite3VdbeAddOp0(v, OP_Null); sqlite3VdbeAddOp0(v, OP_Null);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iLabel); j2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j1);
if( eType==IN_INDEX_ROWID ){ if( eType==IN_INDEX_ROWID ){
int iAddr = sqlite3VdbeCurrentAddr(v)+3; j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, 1);
sqlite3VdbeAddOp2(v, OP_MustBeInt, 1, iAddr); j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable);
sqlite3VdbeAddOp2(v, OP_NotExists, pExpr->iTable, iAddr); j5 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeAddOp2(v, OP_Goto, pExpr->iTable, iLabel); sqlite3VdbeJumpHere(v, j3);
sqlite3VdbeJumpHere(v, j4);
}else{ }else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &affinity, 1);
&affinity, 1); /* addr + 4 */ j5 = sqlite3VdbeAddOp1(v, OP_Found, pExpr->iTable);
sqlite3VdbeAddOp2(v, OP_Found, pExpr->iTable, iLabel);
} }
sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1); /* addr + 6 */ sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1);
sqlite3VdbeResolveLabel(v, iLabel); sqlite3VdbeJumpHere(v, j2);
sqlite3VdbeJumpHere(v, j5);
break; break;
} }
#endif #endif
@ -2485,7 +2485,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
assert( TK_ISNULL==OP_IsNull ); assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull ); assert( TK_NOTNULL==OP_NotNull );
sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pLeft, 0);
sqlite3VdbeAddOp2(v, op, 1, dest); sqlite3VdbeAddOp2(v, op, 0, dest);
break; break;
} }
case TK_BETWEEN: { case TK_BETWEEN: {
@ -2597,7 +2597,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNULL: case TK_ISNULL:
case TK_NOTNULL: { case TK_NOTNULL: {
sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pLeft, 0);
sqlite3VdbeAddOp2(v, op, 1, dest); sqlite3VdbeAddOp2(v, op, 0, dest);
break; break;
} }
case TK_BETWEEN: { case TK_BETWEEN: {

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite. ** 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" #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 ** Write out code to initialize the autoincrement logic. This code
** looks up the current autoincrement value in the sqlite_sequence ** looks up the current autoincrement value in the sqlite_sequence
** table and stores that value in a memory cell. Code generated by ** table and stores that value in a register. Code generated by
** autoIncStep() will keep that memory cell holding the largest ** autoIncStep() will keep that register holding the largest
** rowid value. Code generated by autoIncEnd() will write the new ** rowid value. Code generated by autoIncEnd() will write the new
** largest value of the counter back into the sqlite_sequence table. ** largest value of the counter back into the sqlite_sequence table.
** **
** This routine returns the index of the mem[] cell that contains ** This routine returns the index of the mem[] cell that contains
** the maximum rowid counter. ** the maximum rowid counter.
** **
** Two memory cells are allocated. The next memory cell befor the ** Three consecutive registers are allocated by this routine. The
** one returned holds the rowid in sqlite_sequence where we will ** first two hold the name of the target table and the maximum rowid
** write back the revised 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( static int autoIncBegin(
Parse *pParse, /* Parsing context */ Parse *pParse, /* Parsing context */
int iDb, /* Index of the database holding pTab */ int iDb, /* Index of the database holding pTab */
Table *pTab /* The table we are writing to */ Table *pTab /* The table we are writing to */
){ ){
int memId = 0; int memId = 0; /* Register holding maximum rowid */
if( pTab->autoInc ){ if( pTab->autoInc ){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb]; Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab; int iCur = pParse->nTab;
int addr; int addr; /* Address of the top of the loop */
assert( v ); assert( v );
addr = sqlite3VdbeCurrentAddr(v); pParse->nMem++; /* Holds name of table */
pParse->nMem += 2; memId = ++pParse->nMem;
memId = pParse->nMem; pParse->nMem++;
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); 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); sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11); sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+7);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1);
sqlite3VdbeAddOp2(v, OP_Move, 0, memId-1); sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId);
sqlite3VdbeAddOp2(v, OP_Column, iCur, 1); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8);
sqlite3VdbeAddOp2(v, OP_Move, 0, memId); sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12);
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3);
sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
} }
return memId; return memId;
@ -189,15 +191,15 @@ static int autoIncBegin(
** larger than the maximum rowid in the memId memory cell, then the ** larger than the maximum rowid in the memId memory cell, then the
** memory cell is updated. The stack is unchanged. ** 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 ){ 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 ** 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. ** the sqlite_sequence table.
*/ */
static void autoIncEnd( static void autoIncEnd(
@ -210,19 +212,18 @@ static void autoIncEnd(
int iCur = pParse->nTab; int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb]; Db *pDb = &pParse->db->aDb[iDb];
int addr; int j1;
assert( v ); assert( v );
addr = sqlite3VdbeCurrentAddr(v);
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
sqlite3VdbeAddOp2(v, OP_SCopy, memId-1, 0); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6); sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp1(v, OP_NewRowid, iCur); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1);
sqlite3VdbeAddOp2(v, OP_SCopy, memId, 0); sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0); sqlite3VdbeChangeP5(v, -1, OPFLAG_APPEND);
sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND); sqlite3VdbeAddOp1(v, OP_Close, iCur);
sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
} }
} }
#else #else
@ -341,32 +342,38 @@ void sqlite3Insert(
IdList *pColumn, /* Column names corresponding to IDLIST. */ IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError /* How to handle constraint errors */ 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 */ char *zTab; /* Name of the table into which we are inserting */
const char *zDb; /* Name of the database holding this table */ const char *zDb; /* Name of the database holding this table */
int i, j, idx; /* Loop counters */ int i, j, idx; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */ Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */ Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */ 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 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 keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */ int endOfLoop; /* Label for the end of the insertion loop */
int useTempTable = 0; /* Store SELECT results in intermediate table */ int useTempTable = 0; /* Store SELECT results in intermediate table */
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ 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 iSelectLoop = 0; /* Address of code that implements the SELECT */
int iCleanup = 0; /* Address of the cleanup code */ int iCleanup = 0; /* Address of the cleanup code */
int iInsertBlock = 0; /* Address of the subroutine used to insert data */ int iInsertBlock = 0; /* Address of the subroutine used to insert data */
int iCntMem = 0; /* Memory cell used for the row counter */ int newIdx = -1; /* Cursor for the NEW pseudo-table */
int iBaseReg; /* Base register for data */ int iDb; /* Index of database holding TABLE */
int newIdx = -1; /* Cursor for the NEW table */
Db *pDb; /* The database containing table being inserted into */ 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 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 #ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */ int isView; /* True if attempting to insert into a view */
@ -455,11 +462,9 @@ void sqlite3Insert(
#endif /* SQLITE_OMIT_XFER_OPT */ #endif /* SQLITE_OMIT_XFER_OPT */
/* If this is an AUTOINCREMENT table, look up the sequence number in the /* If this is an AUTOINCREMENT table, look up the sequence number in the
** sqlite_sequence table and store it in memory cell counterMem. Also ** sqlite_sequence table and store it in memory cell regAutoinc.
** remember the rowid of the sqlite_sequence table entry in memory cell
** counterRowid.
*/ */
counterMem = autoIncBegin(pParse, iDb, pTab); regAutoinc = autoIncBegin(pParse, iDb, pTab);
/* Figure out how many columns of data are supplied. If the data /* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates ** is coming from a SELECT statement, then this step also generates
@ -486,7 +491,7 @@ void sqlite3Insert(
goto insert_cleanup; goto insert_cleanup;
} }
iBaseReg = dest.iMem; regFromSelect = dest.iMem;
iCleanup = sqlite3VdbeMakeLabel(v); iCleanup = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup); sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup);
assert( pSelect->pEList ); assert( pSelect->pEList );
@ -510,7 +515,7 @@ void sqlite3Insert(
*/ */
srcTab = pParse->nTab++; srcTab = pParse->nTab++;
sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3VdbeAddOp2(v, OP_RegMakeRec, iBaseReg, nColumn); sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn);
sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab); sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab);
sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND); sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
@ -620,8 +625,8 @@ void sqlite3Insert(
/* Initialize the count of rows to be inserted /* Initialize the count of rows to be inserted
*/ */
if( db->flags & SQLITE_CountRows ){ if( db->flags & SQLITE_CountRows ){
iCntMem = ++pParse->nMem; regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, iCntMem); sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
} }
/* If this is not a view, open the table and and all indices */ /* If this is not a view, open the table and and all indices */
@ -642,10 +647,22 @@ void sqlite3Insert(
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3RegToStack(pParse, iBaseReg, nColumn); sqlite3RegToStack(pParse, regFromSelect, nColumn);
sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); 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 /* Run the BEFORE and INSTEAD OF triggers, if there are any
*/ */
endOfLoop = sqlite3VdbeMakeLabel(v); endOfLoop = sqlite3VdbeMakeLabel(v);
@ -662,12 +679,15 @@ void sqlite3Insert(
}else if( useTempTable ){ }else if( useTempTable ){
sqlite3VdbeAddOp2(v, OP_Column, srcTab, keyColumn); sqlite3VdbeAddOp2(v, OP_Column, srcTab, keyColumn);
}else{ }else{
int j1;
assert( pSelect==0 ); /* Otherwise useTempTable is true */ assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp0(v, OP_SCopy);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
sqlite3VdbeAddOp2(v, OP_Integer, -1, 0); sqlite3VdbeAddOp1(v, OP_Pop, 1);
sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp1(v, OP_Integer, -1);
sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp0(v, OP_MustBeInt);
} }
/* Cannot have triggers on a virtual table. If it were possible, /* 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. ** case the record number is the same as that column.
*/ */
if( !isView ){ 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) ){ if( IsVirtual(pTab) ){
/* The row that the VUpdate opcode will delete: none */ /* 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( keyColumn>=0 ){
if( useTempTable ){ if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid); sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
}else if( pSelect ){ }else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), iRowid); sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid);
}else{ }else{
VdbeOp *pOp; VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
@ -740,36 +756,36 @@ void sqlite3Insert(
appendFlag = 1; appendFlag = 1;
pOp->opcode = OP_NewRowid; pOp->opcode = OP_NewRowid;
pOp->p1 = base; pOp->p1 = base;
pOp->p2 = iRowid; pOp->p2 = regRowid;
pOp->p3 = counterMem; pOp->p3 = regAutoinc;
}else{ }else{
/* TODO: Avoid this use of the stack. */ /* 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 /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value. ** to generate a unique primary key value.
*/ */
if( !appendFlag ){ 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); sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem); sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc);
sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, iRowid); sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regRowid);
} }
}else if( IsVirtual(pTab) ){ }else if( IsVirtual(pTab) ){
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid); sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
}else{ }else{
sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem); sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc);
appendFlag = 1; appendFlag = 1;
} }
autoIncStep(pParse, counterMem, iRowid); autoIncStep(pParse, regAutoinc, regRowid);
/* Push onto the stack, data for all columns of the new entry, beginning /* Push onto the stack, data for all columns of the new entry, beginning
** with the first column. ** with the first column.
*/ */
nHidden = 0; nHidden = 0;
for(i=0; i<pTab->nCol; i++){ for(i=0; i<pTab->nCol; i++){
int iRegStore = iRowid+1+i; int iRegStore = regRowid+1+i;
if( i==pTab->iPKey ){ if( i==pTab->iPKey ){
/* The value of the INTEGER PRIMARY KEY column is always a NULL. /* The value of the INTEGER PRIMARY KEY column is always a NULL.
** Whenever this column is read, the record number will be substituted ** Whenever this column is read, the record number will be substituted
@ -808,12 +824,12 @@ void sqlite3Insert(
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){ if( IsVirtual(pTab) ){
pParse->pVirtualLock = 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); (const char*)pTab->pVtab, P4_VTAB);
}else }else
#endif #endif
{ {
sqlite3RegToStack(pParse, iReg, pTab->nCol+1); sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop); 0, onError, endOfLoop);
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
@ -825,7 +841,7 @@ void sqlite3Insert(
/* Update the count of rows that are inserted /* Update the count of rows that are inserted
*/ */
if( (db->flags & SQLITE_CountRows)!=0 ){ if( (db->flags & SQLITE_CountRows)!=0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, iCntMem, 1); sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
} }
if( triggers_exist ){ if( triggers_exist ){
@ -858,10 +874,10 @@ void sqlite3Insert(
} }
/* Update the sqlite_sequence table by storing the content of the /* 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. ** table.
*/ */
autoIncEnd(pParse, iDb, pTab, counterMem); autoIncEnd(pParse, iDb, pTab, regAutoinc);
/* /*
** Return the number of rows inserted. If this routine is ** Return the number of rows inserted. If this routine is
@ -869,7 +885,7 @@ void sqlite3Insert(
** invoke the callback function. ** invoke the callback function.
*/ */
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ 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); sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC); 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) ** When this routine is called, the stack contains (from bottom to top)
** the following values: ** the following values:
** **
** 1. The rowid of the row to be updated before the update. This ** 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 ** 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. ** 2. The rowid of the row after the update.
** **
@ -1004,7 +1020,7 @@ void sqlite3GenerateConstraintChecks(
onError = OE_Abort; onError = OE_Abort;
} }
sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i)); 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 assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace ); || onError==OE_Ignore || onError==OE_Replace );
switch( onError ){ switch( onError ){
@ -1413,7 +1429,7 @@ static int xferOptimization(
int emptySrcTest; /* Address of test for empty pSrc */ int emptySrcTest; /* Address of test for empty pSrc */
Vdbe *v; /* The VDBE we are building */ Vdbe *v; /* The VDBE we are building */
KeyInfo *pKey; /* Key information for an index */ 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 */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
if( pSelect==0 ){ if( pSelect==0 ){
@ -1541,7 +1557,7 @@ static int xferOptimization(
sqlite3CodeVerifySchema(pParse, iDbSrc); sqlite3CodeVerifySchema(pParse, iDbSrc);
iSrc = pParse->nTab++; iSrc = pParse->nTab++;
iDest = pParse->nTab++; iDest = pParse->nTab++;
counterMem = autoIncBegin(pParse, iDbDest, pDest); regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){
/* If tables do not have an INTEGER PRIMARY KEY and there /* 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, sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
"PRIMARY KEY must be unique", P4_STATIC); "PRIMARY KEY must be unique", P4_STATIC);
sqlite3VdbeJumpHere(v, addr2); sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, counterMem, 0); autoIncStep(pParse, regAutoinc, 0);
}else if( pDest->pIndex==0 ){ }else if( pDest->pIndex==0 ){
addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest); addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest);
}else{ }else{
@ -1580,7 +1596,7 @@ static int xferOptimization(
sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); 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(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file contains code used to implement the PRAGMA command. ** 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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -882,7 +882,7 @@ void sqlite3Pragma(
} }
if( cnt==0 ) continue; if( cnt==0 ) continue;
sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i); 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, sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC); P4_DYNAMIC);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** 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" #include "sqliteInt.h"
@ -809,12 +809,16 @@ static void generateSortTail(
} }
#ifndef SQLITE_OMIT_SUBQUERY #ifndef SQLITE_OMIT_SUBQUERY
case SRT_Set: { case SRT_Set: {
int j1, j2;
assert( nColumn==1 ); assert( nColumn==1 );
sqlite3VdbeAddOp2(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp0(v, OP_SCopy);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); j1 = sqlite3VdbeAddOp0(v, OP_NotNull);
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp1(v, OP_Pop, 1);
j2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
sqlite3VdbeJumpHere(v, j2);
break; break;
} }
case SRT_Mem: { case SRT_Mem: {

View File

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** 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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -2110,7 +2110,7 @@ case OP_IfNot: { /* no-push, jump */
break; 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 ** 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 ** 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 ** pop -P1 elements from the stack only if the jump is taken and leave
** the stack unchanged if the jump is not taken. ** 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 ){ if( pTos->flags & MEM_Null ){
pc = pOp->p2-1; pc = pOp->p2-1;
if( pOp->p1<0 ){ if( pOp->p1<0 ){
@ -2131,40 +2131,31 @@ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */
break; break;
} }
/* Opcode: AnyNull P1 P2 P3 * * /* Opcode: IsNull P1 P2 *
** **
** Check P3 registers beginning with P1. If any are NULL then jump ** Jump to P2 if the value in register P1 is NULL.
** to P2. **
** 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 */ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump, in1 */
int n = pOp->p3; if( (pIn1->flags & MEM_Null)!=0 ){
assert( n>0 && pOp->p1+n<=p->nMem ); pc = pOp->p2 - 1;
while( n>0 ){
if( pIn1->flags & MEM_Null ){
pc = pOp->p2-1;
break;
}
n--;
pIn1++;
} }
break; break;
} }
/* Opcode: NotNull P1 P2 * /* Opcode: NotNull P1 P2 *
** **
** Jump to P2 if the top abs(P1) values on the stack are all not NULL. ** Jump to P2 if the value in register P1 is 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, ** If P1 is 0 then use the top of the stack instead of a register
** leave the stack unchanged. ** and pop the stack regardless of whether or not the jump is taken.
*/ */
case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump */ case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump, in1 */
int i, cnt; if( (pIn1->flags & MEM_Null)==0 ){
cnt = pOp->p1; pc = pOp->p2 - 1;
if( cnt<0 ) cnt = -cnt; }
assert( &pTos[1-cnt] >= p->aStack );
for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
if( i>=cnt ) pc = pOp->p2-1;
if( pOp->p1>0 ) popStack(&pTos, cnt);
break; break;
} }

View File

@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting ** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer". ** 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" #include "sqliteInt.h"
@ -1757,7 +1757,7 @@ static void codeEqualityTerm(
pIn += pLevel->nIn - 1; pIn += pLevel->nIn - 1;
pIn->iCur = iTab; pIn->iCur = iTab;
pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0); pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0);
sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0); sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
}else{ }else{
pLevel->nIn = 0; pLevel->nIn = 0;
} }
@ -1824,7 +1824,7 @@ static void codeAllEqualityTerms(
assert( (pTerm->flags & TERM_CODED)==0 ); assert( (pTerm->flags & TERM_CODED)==0 );
codeEqualityTerm(pParse, pTerm, pLevel); codeEqualityTerm(pParse, pTerm, pLevel);
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ 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 ){ if( termsInMem ){
sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1); sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1);
@ -2467,7 +2467,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr; pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 ); assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight, 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); topEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm); disableTerm(pLevel, pTerm);
testOp = OP_IdxGE; testOp = OP_IdxGE;
@ -2511,7 +2511,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr; pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 ); assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight, 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); btmEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm); disableTerm(pLevel, pTerm);
}else{ }else{
@ -2553,7 +2553,7 @@ WhereInfo *sqlite3WhereBegin(
} }
if( topLimit | btmLimit ){ if( topLimit | btmLimit ){
sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq); sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
sqlite3VdbeAddOp2(v, OP_IsNull, 1, cont); sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont);
} }
if( !omitTable ){ if( !omitTable ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0); sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression # This file implements some common TCL routines used for regression
# testing the SQLite library # 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 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 # Use the pager codec if it is available
# #
@ -86,7 +100,6 @@ set nErr 0
set nTest 0 set nTest 0
set skip_test 0 set skip_test 0
set failList {} set failList {}
set maxErr 1000
if {![info exists speedTest]} { if {![info exists speedTest]} {
set speedTest 0 set speedTest 0
} }