1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-08 03:22:21 +03:00

Continued work toward converting to a register-based VM. (CVS 4698)

FossilOrigin-Name: 92deff07bba2089bbe011f44defb3a0ac1362d56
This commit is contained in:
drh
2008-01-09 02:15:38 +00:00
parent 3557335658
commit 3c84ddff3e
10 changed files with 159 additions and 240 deletions

View File

@@ -1,5 +1,5 @@
C Registerify\sthe\scomparison\sopcodes.\s(CVS\s4697) C Continued\swork\stoward\sconverting\sto\sa\sregister-based\sVM.\s(CVS\s4698)
D 2008-01-08T23:54:25 D 2008-01-09T02:15:39
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 971f5f774d121cfb790630a878a54c939b5b1494 F src/delete.c 971f5f774d121cfb790630a878a54c939b5b1494
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 26b29dabea522d13b8da8cb41b35ed61aca6706c F src/expr.c f1bee4f35fef3078fdbf9075f2b18e41202ccb09
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 c79591d68740681bc28883206763595168ef15d4 F src/insert.c 4443b9026fe9be6c64a689879c564dcd8b7cbcb3
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 ebf841efccc8d2df410fc10aa556a64256457ab4 F src/pragma.c 355d53bc64b70d2dfcd9a1c4a9c5c2ea87da2857
F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
F src/select.c d6bdf86c76c899991f7339291f124718028e8446 F src/select.c 8570d4db93e115227393fd3cdf88be28d9ac585b
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
@@ -164,11 +164,11 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
F src/trigger.c 1e77b3c21c129ad01f7f23a497ae1d224b4e5bc4 F src/trigger.c 1e77b3c21c129ad01f7f23a497ae1d224b4e5bc4
F src/update.c 89ba318306daa20d901ed698018fe6e3d16b3586 F src/update.c 93c7bca744988798c8898d024512954683e3e370
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 926b4630c583f355d5c7376ebc17d82f43a91866 F src/vdbe.c cf1f4de3b96226da2b53fd01b843d5bb0d58f723
F src/vdbe.h c686e1b73011e74b764971b83c97069ece3c04cb F src/vdbe.h c686e1b73011e74b764971b83c97069ece3c04cb
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 a94f3e9e85578ba457133ad3446fc6114a03ec5a F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
F src/where.c 8f55e7257daf93d9c715df7cb312dede6f2d45d2 F src/where.c 8c2bedcc61961a470c358b8c1466c7d8915bc722
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
@@ -605,7 +605,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 5fd1036788dbbc48ff1c746d2e1ba12b04a7e58c P 8862ce9ceefba4f5d1ffbd51d824c05f42a58c22
R 22639e8ca20a12d23612d55375b01a67 R 0091ff2603f4efdcadacf8e9bc937331
U drh U drh
Z 654c7ee149d8fd3c6129fb629505622c Z 95c6f21519b46535c3e92448c74b125f

View File

@@ -1 +1 @@
8862ce9ceefba4f5d1ffbd51d824c05f42a58c22 92deff07bba2089bbe011f44defb3a0ac1362d56

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.338 2008/01/08 23:54:25 drh Exp $ ** $Id: expr.c,v 1.339 2008/01/09 02:15:39 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -2121,10 +2121,14 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
}else{ }else{
codeInteger(v, (char*)p->z, p->n, 1, target); codeInteger(v, (char*)p->z, p->n, 1, target);
} }
inReg = target; }else{
break; int r1 = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
sqlite3ExprCode(pParse, pExpr->pLeft, target);
sqlite3VdbeAddOp3(v, OP_Subtract, target, r1, target);
} }
/* Fall through into TK_NOT */ inReg = target;
break;
} }
case TK_BITNOT: case TK_BITNOT:
case TK_NOT: { case TK_NOT: {
@@ -2245,7 +2249,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
j2 = sqlite3VdbeAddOp0(v, OP_Goto); j2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
if( eType==IN_INDEX_ROWID ){ if( eType==IN_INDEX_ROWID ){
j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, 1); j3 = sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, 1);
j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable); j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable);
j5 = sqlite3VdbeAddOp0(v, OP_Goto); j5 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j3); sqlite3VdbeJumpHere(v, j3);
@@ -2314,7 +2318,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
OP_Ne, 0, 0, 0, SQLITE_JUMPIFNULL); OP_Ne, 0, 0, 0, SQLITE_JUMPIFNULL);
sqlite3VdbeAddOp1(v, OP_Pop, 1); sqlite3VdbeAddOp1(v, OP_Pop, 1);
}else{ }else{
jumpInst = sqlite3VdbeAddOp2(v, OP_IfNot, 1, 0); jumpInst = sqlite3VdbeAddOp3(v, OP_IfNot, 0, 0, 1);
} }
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, expr_end_label); sqlite3VdbeAddOp2(v, OP_Goto, 0, expr_end_label);
@@ -2513,7 +2517,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
} }
default: { default: {
sqlite3ExprCode(pParse, pExpr, 0); sqlite3ExprCode(pParse, pExpr, 0);
sqlite3VdbeAddOp2(v, OP_If, jumpIfNull, dest); sqlite3VdbeAddOp3(v, OP_If, 0, dest, jumpIfNull!=0);
break; break;
} }
} }
@@ -2627,7 +2631,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
} }
default: { default: {
sqlite3ExprCode(pParse, pExpr, 0); sqlite3ExprCode(pParse, pExpr, 0);
sqlite3VdbeAddOp2(v, OP_IfNot, jumpIfNull, dest); sqlite3VdbeAddOp3(v, OP_IfNot, 0, dest, jumpIfNull!=0);
break; break;
} }
} }

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.218 2008/01/08 23:54:25 drh Exp $ ** $Id: insert.c,v 1.219 2008/01/09 02:15:39 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -779,10 +779,10 @@ void sqlite3Insert(
** to generate a unique primary key value. ** to generate a unique primary key value.
*/ */
if( !appendFlag ){ if( !appendFlag ){
sqlite3VdbeAddOp2(v, OP_IfMemNull, regRowid, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
} }
}else if( IsVirtual(pTab) ){ }else if( IsVirtual(pTab) ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);

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.162 2008/01/07 19:20:25 drh Exp $ ** $Id: pragma.c,v 1.163 2008/01/09 02:15:39 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -298,13 +298,13 @@ void sqlite3Pragma(
*/ */
if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
static const VdbeOpList getCacheSize[] = { static const VdbeOpList getCacheSize[] = {
{ OP_ReadCookie, 0, 0, 2}, /* 0 */ { OP_ReadCookie, 0, 1, 2}, /* 0 */
{ OP_AbsValue, 0, 0, 0}, { OP_IfPos, 1, 6, 0},
{ OP_Copy, 0, 0, 0}, { OP_Integer, 0, 2, 0},
{ OP_Integer, 0, 0, 0}, { OP_Subtract, 1, 2, 1},
{ OP_Ne, 0, 6, 0}, { OP_IfPos, 1, 6, 0},
{ OP_Integer, 0, 0, 0}, /* 5 */ { OP_Integer, 0, 1, 0}, /* 5 */
{ OP_Callback, 1, 0, 0}, { OP_ResultRow, 1, 1, 0},
}; };
int addr; int addr;
if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( sqlite3ReadSchema(pParse) ) goto pragma_out;
@@ -312,6 +312,7 @@ void sqlite3Pragma(
if( !zRight ){ if( !zRight ){
sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC);
pParse->nMem += 2;
addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE);
@@ -319,11 +320,11 @@ void sqlite3Pragma(
int size = atoi(zRight); int size = atoi(zRight);
if( size<0 ) size = -size; if( size<0 ) size = -size;
sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, size, 0); sqlite3VdbeAddOp1(v, OP_Integer, size);
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 2); sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 2);
addr = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); addr = sqlite3VdbeAddOp2(v, OP_IfPos, 0, 0);
sqlite3VdbeAddOp2(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp1(v, OP_Integer, -size);
sqlite3VdbeAddOp2(v, OP_Negative, 0, 0); sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 2); sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 2);
pDb->pSchema->cache_size = size; pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
@@ -493,10 +494,10 @@ void sqlite3Pragma(
} }
sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
addr = sqlite3VdbeAddOp2(v, OP_IncrVacuum, iDb, 0); addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb);
sqlite3VdbeAddOp2(v, OP_Callback, 0, 0); sqlite3VdbeAddOp0(v, OP_Callback);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeAddOp2(v, OP_IfMemPos, 1, addr); sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
}else }else
#endif #endif
@@ -863,7 +864,7 @@ void sqlite3Pragma(
if( OMIT_TEMPDB && i==1 ) continue; if( OMIT_TEMPDB && i==1 ) continue;
sqlite3CodeVerifySchema(pParse, i); sqlite3CodeVerifySchema(pParse, i);
addr = sqlite3VdbeAddOp2(v, OP_IfMemPos, 1, 0); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
@@ -899,7 +900,7 @@ void sqlite3Pragma(
int loopTop; int loopTop;
if( pTab->pIndex==0 ) continue; if( pTab->pIndex==0 ) continue;
addr = sqlite3VdbeAddOp2(v, OP_IfMemPos, 1, 0); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
@@ -945,7 +946,7 @@ void sqlite3Pragma(
{ OP_Callback, 1, 0, 0}, { OP_Callback, 1, 0, 0},
}; };
if( pIdx->tnum==0 ) continue; if( pIdx->tnum==0 ) continue;
addr = sqlite3VdbeAddOp2(v, OP_IfMemPos, 1, 0); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);

View File

@@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema ** interface, and routines that contribute to loading the database schema
** from disk. ** from disk.
** **
** $Id: prepare.c,v 1.70 2008/01/03 07:09:48 danielk1977 Exp $ ** $Id: prepare.c,v 1.71 2008/01/09 02:15:39 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -269,6 +269,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
size = meta[2]; size = meta[2];
if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
if( size<0 ) size = -size;
pDb->pSchema->cache_size = size; pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);

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.393 2008/01/08 23:54:25 drh Exp $ ** $Id: select.c,v 1.394 2008/01/09 02:15:42 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -398,18 +398,18 @@ static void pushOntoSorter(
){ ){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
sqlite3ExprCodeExprList(pParse, pOrderBy, 0); sqlite3ExprCodeExprList(pParse, pOrderBy, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, 0); sqlite3VdbeAddOp1(v, OP_Sequence, pOrderBy->iECursor);
sqlite3VdbeAddOp2(v, OP_Pull, pOrderBy->nExpr + 1, 0); sqlite3VdbeAddOp1(v, OP_Pull, pOrderBy->nExpr + 1);
sqlite3VdbeAddOp2(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0); sqlite3VdbeAddOp1(v, OP_MakeRecord, pOrderBy->nExpr + 2);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, 0); sqlite3VdbeAddOp1(v, OP_IdxInsert, pOrderBy->iECursor);
if( pSelect->iLimit>=0 ){ if( pSelect->iLimit>=0 ){
int addr1, addr2; int addr1, addr2;
addr1 = sqlite3VdbeAddOp2(v, OP_IfMemZero, pSelect->iLimit+1, 0); addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1);
sqlite3VdbeAddOp2(v, OP_AddImm, pSelect->iLimit+1, -1); sqlite3VdbeAddOp2(v, OP_AddImm, pSelect->iLimit+1, -1);
addr2 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Last, pOrderBy->iECursor, 0); sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
sqlite3VdbeAddOp2(v, OP_Delete, pOrderBy->iECursor, 0); sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
sqlite3VdbeJumpHere(v, addr2); sqlite3VdbeJumpHere(v, addr2);
pSelect->iLimit = -1; pSelect->iLimit = -1;
} }
@@ -427,9 +427,9 @@ static void codeOffset(
if( p->iOffset>=0 && iContinue!=0 ){ if( p->iOffset>=0 && iContinue!=0 ){
int addr; int addr;
sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
addr = sqlite3VdbeAddOp2(v, OP_IfMemNeg, p->iOffset, 0); addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);
if( nPop>0 ){ if( nPop>0 ){
sqlite3VdbeAddOp2(v, OP_Pop, nPop, 0); sqlite3VdbeAddOp1(v, OP_Pop, nPop);
} }
sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
VdbeComment((v, "skip OFFSET records")); VdbeComment((v, "skip OFFSET records"));
@@ -641,7 +641,7 @@ static int selectInnerLoop(
int addr2; int addr2;
assert( nColumn==1 ); assert( nColumn==1 );
addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem, 0); addr2 = sqlite3VdbeAddOp2(v, OP_IsNull, iMem, 0);
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity); p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
if( pOrderBy ){ if( pOrderBy ){
/* At first glance you would think we could optimize out the /* At first glance you would think we could optimize out the
@@ -717,7 +717,7 @@ static int selectInnerLoop(
*/ */
if( p->iLimit>=0 && pOrderBy==0 ){ if( p->iLimit>=0 && pOrderBy==0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
sqlite3VdbeAddOp2(v, OP_IfMemZero, p->iLimit, iBreak); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
} }
return 0; return 0;
} }
@@ -852,7 +852,7 @@ static void generateSortTail(
*/ */
if( p->iLimit>=0 ){ if( p->iLimit>=0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
sqlite3VdbeAddOp2(v, OP_IfMemZero, p->iLimit, brk); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, brk);
} }
/* The bottom of the loop /* The bottom of the loop
@@ -1768,10 +1768,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
if( v==0 ) return; if( v==0 ) return;
sqlite3ExprCode(pParse, p->pLimit, 0); sqlite3ExprCode(pParse, p->pLimit, 0);
sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp0(v, OP_MustBeInt);
sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit); sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit);
VdbeComment((v, "LIMIT counter")); VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfMemZero, iLimit, iBreak); sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0); sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0);
} }
if( p->pOffset ){ if( p->pOffset ){
@@ -1779,10 +1779,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
if( v==0 ) return; if( v==0 ) return;
sqlite3ExprCode(pParse, p->pOffset, 0); sqlite3ExprCode(pParse, p->pOffset, 0);
sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp0(v, OP_MustBeInt);
sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset); sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset);
VdbeComment((v, "OFFSET counter")); VdbeComment((v, "OFFSET counter"));
addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iOffset, 0); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
@@ -1791,10 +1791,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
} }
} }
if( p->pLimit ){ if( p->pLimit ){
addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iLimit, 0); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp1(v, OP_Pop, 1);
sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1); sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1);
addr2 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1); sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1);
VdbeComment((v, "LIMIT+OFFSET")); VdbeComment((v, "LIMIT+OFFSET"));
@@ -1948,7 +1948,7 @@ static int multiSelect(
p->iLimit = pPrior->iLimit; p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset; p->iOffset = pPrior->iOffset;
if( p->iLimit>=0 ){ if( p->iLimit>=0 ){
addr = sqlite3VdbeAddOp2(v, OP_IfMemZero, p->iLimit, 0); addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
VdbeComment((v, "Jump ahead if LIMIT reached")); VdbeComment((v, "Jump ahead if LIMIT reached"));
} }
rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff); rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff);
@@ -3520,7 +3520,7 @@ int sqlite3Select(
VdbeComment((v, "set abort flag")); VdbeComment((v, "set abort flag"));
sqlite3VdbeAddOp2(v, OP_Return, 0, 0); sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
addrOutputRow = sqlite3VdbeCurrentAddr(v); addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
VdbeComment((v, "Groupby result generator entry point")); VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp2(v, OP_Return, 0, 0); sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
finalizeAggFunctions(pParse, &sAggInfo); finalizeAggFunctions(pParse, &sAggInfo);
@@ -3626,7 +3626,7 @@ int sqlite3Select(
} }
sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow);
VdbeComment((v, "output one row")); VdbeComment((v, "output one row"));
sqlite3VdbeAddOp2(v, OP_IfMemPos, iAbortFlag, addrEnd); sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
VdbeComment((v, "check abort flag")); VdbeComment((v, "check abort flag"));
sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset); sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset);
VdbeComment((v, "reset accumulator")); VdbeComment((v, "reset accumulator"));

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 UPDATE statements. ** to handle UPDATE statements.
** **
** $Id: update.c,v 1.164 2008/01/08 18:57:50 drh Exp $ ** $Id: update.c,v 1.165 2008/01/09 02:15:42 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -468,7 +468,7 @@ void sqlite3Update(
*/ */
if( chngRowid ){ if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regNewRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
} }
/* Compute new data for this record. /* Compute new data for this record.

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.689 2008/01/08 23:54:25 drh Exp $ ** $Id: vdbe.c,v 1.690 2008/01/09 02:15:42 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -913,7 +913,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
break; break;
} }
/* Opcode: String8 * * P4 /* Opcode: String8 * P2 * P4 *
** **
** P4 points to a nul terminated UTF-8 string. This opcode is transformed ** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time. ** into an OP_String before it is executed for the first time.
@@ -1023,7 +1023,7 @@ case OP_Blob: { /* out2-prerelease */
} }
#endif /* SQLITE_OMIT_BLOB_LITERAL */ #endif /* SQLITE_OMIT_BLOB_LITERAL */
/* Opcode: Variable P1 * * /* Opcode: Variable P1 P2 * * *
** **
** The value of variable P1 is written into register P2 or pushed ** The value of variable P1 is written into register P2 or pushed
** onto the stack if P2 is zero. A variable is ** onto the stack if P2 is zero. A variable is
@@ -1046,7 +1046,7 @@ case OP_Variable: { /* out2-prerelease */
break; break;
} }
/* Opcode: Pop P1 * * /* Opcode: Pop P1 * * * *
** **
** P1 elements are popped off of the top of stack and discarded. ** P1 elements are popped off of the top of stack and discarded.
*/ */
@@ -1308,50 +1308,34 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
break; break;
} }
/* Opcode: Add * * * /* Opcode: Add P1 P2 P3 * *
** **
** Pop the top two elements from the stack, add them together, ** Add the value in P1 to the value in P2 and store the result in P3.
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the addition.
** If either operand is NULL, the result is NULL. ** If either operand is NULL, the result is NULL.
*/ */
/* Opcode: Multiply * * * /* Opcode: Multiply P1 P2 P3 * *
** **
** Pop the top two elements from the stack, multiply them together, **
** and push the result back onto the stack. If either element ** Multiply the value in P1 by the value in P2 and store the result in P3.
** is a string then it is converted to a double using the atof()
** function before the multiplication.
** If either operand is NULL, the result is NULL. ** If either operand is NULL, the result is NULL.
*/ */
/* Opcode: Subtract * * * /* Opcode: Subtract P1 P2 P3 * *
** **
** Pop the top two elements from the stack, subtract the ** Subtract the value in P1 from the value in P2 and store the result
** first (what was on top of the stack) from the second (the ** in P3.
** next on stack)
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the subtraction.
** If either operand is NULL, the result is NULL. ** If either operand is NULL, the result is NULL.
*/ */
/* Opcode: Divide * * * /* Opcode: Divide * * *
** **
** Pop the top two elements from the stack, divide the ** Divide the value in P1 by the value in P2 and store the result
** first (what was on top of the stack) from the second (the ** in P3. If the value in P2 is zero, then the result is NULL.
** next on stack)
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
** If either operand is NULL, the result is NULL. ** If either operand is NULL, the result is NULL.
*/ */
/* Opcode: Remainder * * * /* Opcode: Remainder * * *
** **
** Pop the top two elements from the stack, divide the ** Compute the remainder after integer division of the value in
** first (what was on top of the stack) from the second (the ** register P1 by the value in register P2 and store the result in P3.
** next on stack) ** If the value in register P2 is zero the result is NULL.
** and push the remainder after division onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
** If either operand is NULL, the result is NULL. ** If either operand is NULL, the result is NULL.
*/ */
case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */
@@ -1648,35 +1632,32 @@ case OP_ForceInt: { /* no-push, jump, in1 */
/* Opcode: MustBeInt P1 P2 P3 /* Opcode: MustBeInt P1 P2 P3
** **
** Force the top of the stack to be an integer. If the top of the ** Force the value in register P1 to be an integer. If P1==0 then
** stack is not an integer and cannot be converted into an integer ** use the top of the stack. If the value in P1
** is not an integer and cannot be converted into an integer
** without data loss, then jump immediately to P2, or if P2==0 ** without data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception. ** raise an SQLITE_MISMATCH exception.
** **
** If the top of the stack is not an integer and P2 is not zero and ** If the P1==0 and the top of the stack is not an integer
** P1 is 1, then the stack is popped. In all other cases, the depth ** and P2 is not zero and P3 is 1, then the stack is popped.
** of the stack is unchanged. ** In all other cases, the depth of the stack is unchanged.
**
** If P3 is not zero, then act on the value in register P3 instead
** of using the stack.
*/ */
case OP_MustBeInt: { /* no-push, jump */ case OP_MustBeInt: { /* no-push, jump, in1 */
Mem *pMem = ((pOp->p3==0)?pTos:&p->aMem[pOp->p3]); nPop = 0;
assert( pOp->p3 || pTos>=p->aStack ); applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
assert( pOp->p3>=0 && pOp->p3<=p->nMem ); if( (pIn1->flags & MEM_Int)==0 ){
REGISTER_TRACE(pOp->p3, pMem);
applyAffinity(pMem, SQLITE_AFF_NUMERIC, encoding);
if( (pMem->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){ if( pOp->p2==0 ){
rc = SQLITE_MISMATCH; rc = SQLITE_MISMATCH;
goto abort_due_to_error; goto abort_due_to_error;
}else if( pMem==pTos ){ }else{
if( pOp->p1 ) popStack(&pTos, 1); if( pOp->p3 && pOp->p1==0 ){
popStack(&pTos, 1);
}
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
}else{ }else{
Release(pMem); Release(pIn1);
pMem->flags = MEM_Int; pIn1->flags = MEM_Int;
} }
break; break;
} }
@@ -1989,53 +1970,19 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
break; break;
} }
/* Opcode: Negative * * *
**
** Treat the top of the stack as a numeric quantity. Replace it
** with its additive inverse. If the top of the stack is NULL
** its value is unchanged.
*/
/* Opcode: AbsValue * * *
**
** Treat the top of the stack as a numeric quantity. Replace it
** with its absolute value. If the top of the stack is NULL
** its value is unchanged.
*/
case OP_Negative: /* same as TK_UMINUS, no-push */
case OP_AbsValue: {
assert( pTos>=p->aStack );
if( (pTos->flags & (MEM_Real|MEM_Int|MEM_Null))==0 ){
sqlite3VdbeMemNumerify(pTos);
}
if( pTos->flags & MEM_Real ){
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
}
pTos->flags = MEM_Real;
}else if( pTos->flags & MEM_Int ){
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->u.i<0 ){
pTos->u.i = -pTos->u.i;
}
pTos->flags = MEM_Int;
}
break;
}
/* Opcode: Not * * * /* Opcode: Not * * *
** **
** Interpret the top of the stack as a boolean value. Replace it ** Interpret the top of the stack as a boolean value. Replace it
** with its complement. If the top of the stack is NULL its value ** with its complement. If the top of the stack is NULL its value
** is unchanged. ** is unchanged.
*/ */
case OP_Not: { /* same as TK_NOT, no-push */ case OP_Not: { /* same as TK_NOT, no-push, in1 */
assert( pTos>=p->aStack ); nPop = 0;
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pTos); sqlite3VdbeMemIntegerify(pIn1);
assert( (pTos->flags & MEM_Dyn)==0 ); assert( (pIn1->flags & MEM_Dyn)==0 );
pTos->u.i = !pTos->u.i; pIn1->u.i = !pTos->u.i;
pTos->flags = MEM_Int; pIn1->flags = MEM_Int;
break; break;
} }
@@ -2045,13 +1992,13 @@ case OP_Not: { /* same as TK_NOT, no-push */
** with its ones-complement. If the top of the stack is NULL its ** with its ones-complement. If the top of the stack is NULL its
** value is unchanged. ** value is unchanged.
*/ */
case OP_BitNot: { /* same as TK_BITNOT, no-push */ case OP_BitNot: { /* same as TK_BITNOT, no-push, in1 */
assert( pTos>=p->aStack ); nPop = 0;
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pTos); sqlite3VdbeMemIntegerify(pIn1);
assert( (pTos->flags & MEM_Dyn)==0 ); assert( (pIn1->flags & MEM_Dyn)==0 );
pTos->u.i = ~pTos->u.i; pIn1->u.i = ~pTos->u.i;
pTos->flags = MEM_Int; pIn1->flags = MEM_Int;
break; break;
} }
@@ -2071,43 +2018,34 @@ case OP_Noop: { /* no-push */
break; break;
} }
/* Opcode: If P1 P2 * /* Opcode: If P1 P2 P3 * *
** **
** Pop a single boolean from the stack. If the boolean popped is ** Jump to P2 if the value in register P1 is true. The value is
** true, then jump to p2. Otherwise continue to the next instruction. ** is considered true if it is numeric and non-zero. If the value
** An integer is false if zero and true otherwise. A string is ** in P1 is NULL then take the jump if P3 is true.
** false if it has zero length and true otherwise.
**
** If the value popped of the stack is NULL, then take the jump if P1
** is true and fall through if P1 is false.
*/ */
/* Opcode: IfNot P1 P2 * /* Opcode: IfNot P1 P2 P3 * *
** **
** Pop a single boolean from the stack. If the boolean popped is ** Jump to P2 if the value in register P1 is False. The value is
** false, then jump to p2. Otherwise continue to the next instruction. ** is considered true if it has a numeric value of zero. If the value
** An integer is false if zero and true otherwise. A string is ** in P1 is NULL then take the jump if P3 is true.
** false if it has zero length and true otherwise.
**
** If the value popped of the stack is NULL, then take the jump if P1
** is true and fall through if P1 is false.
*/ */
case OP_If: /* no-push, jump */ case OP_If: /* no-push, jump, in1 */
case OP_IfNot: { /* no-push, jump */ case OP_IfNot: { /* no-push, jump, in1 */
int c; int c;
assert( pTos>=p->aStack ); if( pIn1->flags & MEM_Null ){
if( pTos->flags & MEM_Null ){ c = pOp->p3;
c = pOp->p1;
}else{ }else{
#ifdef SQLITE_OMIT_FLOATING_POINT #ifdef SQLITE_OMIT_FLOATING_POINT
c = sqlite3VdbeIntValue(pTos); c = sqlite3VdbeIntValue(pIn1);
#else #else
c = sqlite3VdbeRealValue(pTos)!=0.0; c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif #endif
if( pOp->opcode==OP_IfNot ) c = !c; if( pOp->opcode==OP_IfNot ) c = !c;
} }
Release(pTos); if( c ){
pTos--; pc = pOp->p2-1;
if( c ) pc = pOp->p2-1; }
break; break;
} }
@@ -4758,71 +4696,46 @@ case OP_MemMax: { /* no-push */
} }
#endif /* SQLITE_OMIT_AUTOINCREMENT */ #endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Opcode: IfMemPos P1 P2 * /* Opcode: IfPos P1 P2 *
** **
** If the value of memory cell P1 is 1 or greater, jump to P2. ** If the value of memory cell P1 is 1 or greater, jump to P2.
** **
** It is illegal to use this instruction on a memory cell that does ** It is illegal to use this instruction on a memory cell that does
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemPos: { /* no-push, jump */ case OP_IfPos: { /* no-push, jump, in1 */
int i = pOp->p1; assert( pIn1->flags==MEM_Int );
Mem *pMem; if( pIn1->u.i>0 ){
assert( i>0 && i<=p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->u.i>0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
break; break;
} }
/* Opcode: IfMemNeg P1 P2 * /* Opcode: IfNeg P1 P2 *
** **
** If the value of memory cell P1 is less than zero, jump to P2. ** If the value of memory cell P1 is less than zero, jump to P2.
** **
** It is illegal to use this instruction on a memory cell that does ** It is illegal to use this instruction on a memory cell that does
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemNeg: { /* no-push, jump */ case OP_IfNeg: { /* no-push, jump, in1 */
int i = pOp->p1; assert( pIn1->flags==MEM_Int );
Mem *pMem; if( pIn1->u.i<0 ){
assert( i>0 && i<=p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->u.i<0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
break; break;
} }
/* Opcode: IfMemZero P1 P2 * /* Opcode: IfZero P1 P2 *
** **
** If the value of memory cell P1 is exactly 0, jump to P2. ** If the value of memory cell P1 is exactly 0, jump to P2.
** **
** It is illegal to use this instruction on a memory cell that does ** It is illegal to use this instruction on a memory cell that does
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemZero: { /* no-push, jump */ case OP_IfZero: { /* no-push, jump, in1 */
int i = pOp->p1; assert( pIn1->flags==MEM_Int );
Mem *pMem; if( pIn1->u.i==0 ){
assert( i>0 && i<=p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->u.i==0 ){
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: IfMemNull P1 P2 *
**
** If the value of memory cell P1 is NULL, jump to P2.
*/
case OP_IfMemNull: { /* no-push, jump */
int i = pOp->p1;
assert( i>0 && i<=p->nMem );
if( p->aMem[i].flags & MEM_Null ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
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.278 2008/01/08 23:54:26 drh Exp $ ** $Id: where.c,v 1.279 2008/01/09 02:15:42 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -2329,7 +2329,7 @@ WhereInfo *sqlite3WhereBegin(
assert( omitTable==0 ); assert( omitTable==0 );
codeEqualityTerm(pParse, pTerm, pLevel); codeEqualityTerm(pParse, pTerm, pLevel);
nxt = pLevel->nxt; nxt = pLevel->nxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, 1, nxt); sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, nxt, 1);
sqlite3VdbeAddOp2(v, OP_NotExists, iCur, nxt); sqlite3VdbeAddOp2(v, OP_NotExists, iCur, nxt);
VdbeComment((v, "pk")); VdbeComment((v, "pk"));
pLevel->op = OP_Noop; pLevel->op = OP_Noop;
@@ -2766,10 +2766,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeResolveLabel(v, pLevel->brk); sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->iLeftJoin ){ if( pLevel->iLeftJoin ){
int addr; int addr;
addr = sqlite3VdbeAddOp2(v, OP_IfMemPos, pLevel->iLeftJoin, 0); addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
sqlite3VdbeAddOp2(v, OP_NullRow, pTabList->a[i].iCursor, 0); sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
if( pLevel->iIdxCur>=0 ){ if( pLevel->iIdxCur>=0 ){
sqlite3VdbeAddOp2(v, OP_NullRow, pLevel->iIdxCur, 0); sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
} }
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->top); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->top);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
@@ -2789,10 +2789,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pTab!=0 ); assert( pTab!=0 );
if( pTab->isEphem || pTab->pSelect ) continue; if( pTab->isEphem || pTab->pSelect ) continue;
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp2(v, OP_Close, pTabItem->iCursor, 0); sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
} }
if( pLevel->pIdx!=0 ){ if( pLevel->pIdx!=0 ){
sqlite3VdbeAddOp2(v, OP_Close, pLevel->iIdxCur, 0); sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
} }
/* If this scan uses an index, make code substitutions to read data /* If this scan uses an index, make code substitutions to read data