From 3557335658a74f08cadbe0ce6a5df951528dee9e Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 8 Jan 2008 23:54:25 +0000 Subject: [PATCH] Registerify the comparison opcodes. (CVS 4697) FossilOrigin-Name: 8862ce9ceefba4f5d1ffbd51d824c05f42a58c22 --- manifest | 32 ++++---- manifest.uuid | 2 +- src/analyze.c | 5 +- src/delete.c | 4 +- src/expr.c | 98 ++++++++++++++++--------- src/insert.c | 9 ++- src/select.c | 11 +-- src/sqliteInt.h | 16 +++- src/trigger.c | 2 +- src/vdbe.c | 191 ++++++++++++++++++++++-------------------------- src/vdbe.h | 4 +- src/vdbeaux.c | 10 ++- src/where.c | 11 +-- 13 files changed, 211 insertions(+), 184 deletions(-) diff --git a/manifest b/manifest index b40b7ed61b..48bf47b5ee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Finish\sregisterizing\sthe\score\slogic\sof\sINSERT\sand\sUPDATE.\s(CVS\s4696) -D 2008-01-08T18:57:50 +C Registerify\sthe\scomparison\sopcodes.\s(CVS\s4697) +D 2008-01-08T23:54:25 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -79,7 +79,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04 -F src/analyze.c 96e12e03c101cffaab50be7829d7194184864f42 +F src/analyze.c 6327934f5a4ec38b71f085482df4a05db0a99126 F src/attach.c 1c96631e56cdc51d3d70736bf61f1fe01c62cbea F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff @@ -90,13 +90,13 @@ F src/build.c 22b50a462d7b2be82e29071069d1c3daf29e953f F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 -F src/delete.c d78e46b259a94a5f98a1bceee206c5fd21276ae7 +F src/delete.c 971f5f774d121cfb790630a878a54c939b5b1494 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 6f2a852227ba2abd5ad0916f539c1f2159da28b4 +F src/expr.c 26b29dabea522d13b8da8cb41b35ed61aca6706c F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 -F src/insert.c e46f25f5262b243b60419f6ca5cc4811bf96eec6 +F src/insert.c c79591d68740681bc28883206763595168ef15d4 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 @@ -131,12 +131,12 @@ F src/pragma.c ebf841efccc8d2df410fc10aa556a64256457ab4 F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c 1162f736dbe227a1978f2d2c0e3fc111288f9653 +F src/select.c d6bdf86c76c899991f7339291f124718028e8446 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb -F src/sqliteInt.h fd911a263a5b50015afe01be5501bf5b6be913d0 +F src/sqliteInt.h 884eb3db36efe571ce371309592ad44fefb91c9a F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf @@ -163,21 +163,21 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48 -F src/trigger.c 33071215111825634b85567bfc36c14094eebe54 +F src/trigger.c 1e77b3c21c129ad01f7f23a497ae1d224b4e5bc4 F src/update.c 89ba318306daa20d901ed698018fe6e3d16b3586 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c e71595acce83c585c31ac0551cee1c8cf9540fd2 -F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 +F src/vdbe.c 926b4630c583f355d5c7376ebc17d82f43a91866 +F src/vdbe.h c686e1b73011e74b764971b83c97069ece3c04cb F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c -F src/vdbeaux.c b6241be0277795ecd902743366434704f03b7636 +F src/vdbeaux.c 2f716ebde79aa5bd83231c61269000413d8710f0 F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a -F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb +F src/where.c 8f55e7257daf93d9c715df7cb312dede6f2d45d2 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba @@ -605,7 +605,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 87b4ac4b73fb84411ced9e9a859dd0e2d211c4b3 -R ea42342909fb8c895292e16f7eae74b2 +P 5fd1036788dbbc48ff1c746d2e1ba12b04a7e58c +R 22639e8ca20a12d23612d55375b01a67 U drh -Z c9e18a2ce9ff1c41852f6d73afcc5930 +Z 654c7ee149d8fd3c6129fb629505622c diff --git a/manifest.uuid b/manifest.uuid index 7428ee3025..4f8be3394d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5fd1036788dbbc48ff1c746d2e1ba12b04a7e58c \ No newline at end of file +8862ce9ceefba4f5d1ffbd51d824c05f42a58c22 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 9b5494a2d5..afb9c0af8f 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.34 2008/01/05 16:29:28 drh Exp $ +** @(#) $Id: analyze.c,v 1.35 2008/01/08 23:54:25 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -159,7 +159,8 @@ static void analyzeOneTable( for(i=0; i @@ -158,15 +158,13 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ } /* -** Return the P1 value that should be used for a binary comparison +** Return the P5 value that should be used for a binary comparison ** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. -** If jumpIfNull is true, then set the low byte of the returned -** P1 value to tell the opcode to jump if either expression -** evaluates to NULL. */ -static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ - char aff = sqlite3ExprAffinity(pExpr2); - return ((int)sqlite3CompareAffinity(pExpr1, aff))+(jumpIfNull?0x100:0); +static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + u8 aff = (char)sqlite3ExprAffinity(pExpr2); + aff = sqlite3CompareAffinity(pExpr1, aff) | jumpIfNull; + return aff; } /* @@ -211,13 +209,20 @@ static int codeCompare( Expr *pLeft, /* The left operand */ Expr *pRight, /* The right operand */ int opcode, /* The comparison opcode */ + int in1, int in2, /* Register holding operands */ int dest, /* Jump here if true. */ int jumpIfNull /* If true, jump if either operand is NULL */ ){ - int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull); - CollSeq *p3 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); - return sqlite3VdbeAddOp4(pParse->pVdbe, opcode, p1, dest, 0, - (void*)p3, P4_COLLSEQ); + int p5; + int addr; + CollSeq *p4; + + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); + p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); + addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, + (void*)p4, P4_COLLSEQ); + sqlite3VdbeChangeP5(pParse->pVdbe, p5); + return addr; } /* @@ -2058,15 +2063,22 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ case TK_GE: case TK_NE: case TK_EQ: { + int r1, r2; assert( TK_LT==OP_Lt ); assert( TK_LE==OP_Le ); assert( TK_GT==OP_Gt ); assert( TK_GE==OP_Ge ); assert( TK_EQ==OP_Eq ); assert( TK_NE==OP_Ne ); - sqlite3ExprCode(pParse, pExpr->pLeft, 0); - sqlite3ExprCode(pParse, pExpr->pRight, 0); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); + if( target>0 ){ + inReg = target; + }else{ + inReg = ++pParse->nMem; + } + r1 = sqlite3ExprCode(pParse, pExpr->pLeft, -1); + r2 = sqlite3ExprCode(pParse, pExpr->pRight, -1); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2); break; } case TK_AND: @@ -2205,8 +2217,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ sqlite3CodeSubselect(pParse, pExpr); } inReg = pExpr->iColumn; - /* sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iColumn); - VdbeComment((v, "load subquery result")); */ break; } case TK_IN: { @@ -2254,16 +2264,24 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ Expr *pLeft = pExpr->pLeft; struct ExprList_item *pLItem = pExpr->pList->a; Expr *pRight = pLItem->pExpr; - sqlite3ExprCode(pParse, pLeft, 0); - sqlite3VdbeAddOp0(v, OP_Copy); - sqlite3ExprCode(pParse, pRight, 0); - codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0); - sqlite3VdbeAddOp1(v, OP_Pull, 1); + int r1, r2, r3, r4, r5; + + if( target>0 ){ + inReg = target; + }else{ + inReg = ++pParse->nMem; + } + r1 = sqlite3ExprCode(pParse, pLeft, -1); + r2 = sqlite3ExprCode(pParse, pRight, -1); + r3 = ++pParse->nMem; + codeCompare(pParse, pLeft, pRight, OP_Ge, + r1, r2, r3, SQLITE_STOREP2); pLItem++; pRight = pLItem->pExpr; - sqlite3ExprCode(pParse, pRight, 0); - codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); - sqlite3VdbeAddOp0(v, OP_And); + r4 = sqlite3ExprCode(pParse, pRight, -1); + r5 = ++pParse->nMem; + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r4, r5, SQLITE_STOREP2); + sqlite3VdbeAddOp3(v, OP_And, r3, r5, inReg); break; } case TK_UPLUS: { @@ -2293,7 +2311,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ if( pExpr->pLeft ){ sqlite3VdbeAddOp1(v, OP_SCopy, -1); jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr, - OP_Ne, 0, 1); + OP_Ne, 0, 0, 0, SQLITE_JUMPIFNULL); sqlite3VdbeAddOp1(v, OP_Pop, 1); }else{ jumpInst = sqlite3VdbeAddOp2(v, OP_IfNot, 1, 0); @@ -2411,7 +2429,7 @@ int sqlite3ExprCodeExprList( ** continues straight thru if the expression is false. ** ** If the expression evaluates to NULL (neither true nor false), then -** take the jump if the jumpIfNull flag is true. +** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. ** ** This code depends on the fact that certain token values (ex: TK_EQ) ** are the same as opcode values (ex: OP_Eq) that implement the corresponding @@ -2422,12 +2440,13 @@ int sqlite3ExprCodeExprList( void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; @@ -2455,7 +2474,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ assert( TK_NE==OP_Ne ); sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pRight, 0); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + 0, 0, dest, jumpIfNull); break; } case TK_ISNULL: @@ -2479,11 +2499,12 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprCode(pParse, pLeft, 0); sqlite3VdbeAddOp0(v, OP_Copy); sqlite3ExprCode(pParse, pRight, 0); - addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); + addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, 0, 0, + jumpIfNull ^ SQLITE_JUMPIFNULL); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight, 0); - codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); + codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0, dest, jumpIfNull); sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); sqlite3VdbeJumpHere(v, addr); @@ -2504,11 +2525,13 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ ** continues straight thru if the expression is true. ** ** If the expression evaluates to NULL (neither true nor false) then -** jump if jumpIfNull is true or fall through if jumpIfNull is false. +** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull +** is 0. */ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( v==0 || pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: @@ -2550,7 +2573,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; @@ -2567,7 +2590,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_EQ: { sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3ExprCode(pParse, pExpr->pRight, 0); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + 0, 0, dest, jumpIfNull); break; } case TK_ISNULL: @@ -2590,13 +2614,15 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3VdbeAddOp0(v, OP_Copy); sqlite3ExprCode(pParse, pRight, 0); addr = sqlite3VdbeCurrentAddr(v); - codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull); + codeCompare(pParse, pLeft, pRight, OP_Ge, + 0, 0, addr+3, jumpIfNull ^ SQLITE_JUMPIFNULL); sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); pRight = pExpr->pList->a[1].pExpr; sqlite3ExprCode(pParse, pRight, 0); - codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull); + codeCompare(pParse, pLeft, pRight, OP_Gt, + 0, 0, dest, jumpIfNull); break; } default: { diff --git a/src/insert.c b/src/insert.c index 26f5408e6a..cf6c8ac3ad 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.217 2008/01/08 18:57:50 drh Exp $ +** $Id: insert.c,v 1.218 2008/01/08 23:54:25 drh Exp $ */ #include "sqliteInt.h" @@ -173,7 +173,8 @@ static int autoIncBegin( 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+7); + sqlite3VdbeAddOp2(v, OP_Ne, 0, addr+7); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8); @@ -222,7 +223,7 @@ static void autoIncEnd( 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); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp1(v, OP_Close, iCur); } } @@ -1082,7 +1083,7 @@ void sqlite3GenerateConstraintChecks( if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ int allOk = sqlite3VdbeMakeLabel(v); pParse->ckBase = regData; - sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1); + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL); onError = overrideError!=OE_Default ? overrideError : OE_Abort; if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); diff --git a/src/select.c b/src/select.c index 4e39192d64..6f1d1dc93b 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.392 2008/01/07 19:20:25 drh Exp $ +** $Id: select.c,v 1.393 2008/01/08 23:54:25 drh Exp $ */ #include "sqliteInt.h" @@ -3525,7 +3525,7 @@ int sqlite3Select( sqlite3VdbeAddOp2(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ - sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); } rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, distinct, pDest, @@ -3603,11 +3603,12 @@ int sqlite3Select( } sqlite3VdbeAddOp2(v, OP_SCopy, iAMem+j, 0); if( j==0 ){ - sqlite3VdbeAddOp2(v, OP_Eq, 0x200, addrProcessRow); + sqlite3VdbeAddOp2(v, OP_Eq, 0, addrProcessRow); }else{ - sqlite3VdbeAddOp2(v, OP_Ne, 0x200, addrGroupByChange); + sqlite3VdbeAddOp2(v, OP_Ne, 0, addrGroupByChange); } sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQUAL); } /* Generate code that runs whenever the GROUP BY changes. @@ -3712,7 +3713,7 @@ int sqlite3Select( finalizeAggFunctions(pParse, &sAggInfo); pOrderBy = 0; if( pHaving ){ - sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1); + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); } selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, pDest, addrEnd, addrEnd, aff); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ec6da6da53..b48e1cd627 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.643 2008/01/08 18:57:50 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.644 2008/01/08 23:54:25 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -714,6 +714,20 @@ struct CollSeq { #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_NULLEQUAL 0x10 /* compare NULLs equal */ +#define SQLITE_STOREP2 0x80 /* Store result in reg[P2] rather than jump */ + /* ** Each SQL table is represented in memory by an instance of the ** following structure. diff --git a/src/trigger.c b/src/trigger.c index a5ee6a447e..bd928916c9 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -850,7 +850,7 @@ int sqlite3CodeRowTrigger( sqlite3ExprDelete(whenExpr); return 1; } - sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); + sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL); sqlite3ExprDelete(whenExpr); codeTriggerProgram(pParse, p->step_list, orconf); diff --git a/src/vdbe.c b/src/vdbe.c index 7ac12ffeae..f090e97fad 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.688 2008/01/08 02:57:56 drh Exp $ +** $Id: vdbe.c,v 1.689 2008/01/08 23:54:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -1168,21 +1168,6 @@ case OP_Pull: { /* no-push */ break; } -/* Opcode: Push P1 * * -** -** Overwrite the value of the P1-th element down on the -** stack (P1==0 is the top of the stack) with the value -** of the top of the stack. Then pop the top of the stack. -*/ -case OP_Push: { /* no-push */ - Mem *pTo = &pTos[-pOp->p1]; - - assert( pTo>=p->aStack ); - sqlite3VdbeMemMove(pTo, pTos); - pTos--; - break; -} - /* Opcode: Callback P1 * * ** ** The top P1 values on the stack represent a single result row from @@ -1811,132 +1796,129 @@ case OP_ToReal: { /* same as TK_TO_REAL, no-push, in1 */ } #endif /* SQLITE_OMIT_CAST */ -/* Opcode: Eq P1 P2 P4 +/* Opcode: Lt P1 P2 P3 P4 P5 ** -** Pop the top two elements from the stack. If they are equal, then -** jump to instruction P2. Otherwise, continue to the next instruction. +** Compare the values in register P1 and P3. If reg(P3)flags|pNos->flags; + flags = pIn1->flags|pIn3->flags; /* If either value is a NULL P2 is not zero, take the jump if the least ** significant byte of P1 is true. If P2 is zero, then push a NULL onto ** the stack. */ if( flags&MEM_Null ){ - if( (pOp->p1 & 0x200)!=0 ){ - /* The 0x200 bit of P1 means, roughly "do not treat NULL as the - ** magic SQL value it normally is - treat it as if it were another - ** integer". - ** - ** With 0x200 set, if either operand is NULL then both operands - ** are converted to integers prior to being passed down into the - ** normal comparison logic below. NULL operands are converted to - ** zero and non-NULL operands are converted to 1. Thus, for example, - ** with 0x200 set, NULL==NULL is true whereas it would normally - ** be NULL. Similarly, NULL!=123 is true. + if( (pOp->p5 & SQLITE_NULLEQUAL)!=0 ){ + /* + ** When SQLITE_NULLEQUAL set and either operand is NULL + ** then both operands are converted to integers prior to being + ** passed down into the normal comparison logic below. + ** NULL operands are converted to zero and non-NULL operands + ** are converted to 1. Thus, for example, with SQLITE_NULLEQUAL + ** set, NULL==NULL is true whereas it would normally NULL. + ** Similarly, NULL!=123 is true. */ - sqlite3VdbeMemSetInt64(pTos, (pTos->flags & MEM_Null)==0); - sqlite3VdbeMemSetInt64(pNos, (pNos->flags & MEM_Null)==0); + x1.flags = MEM_Int; + x1.u.i = (pIn1->flags & MEM_Null)==0; + pIn1 = &x1; + x3.flags = MEM_Int; + x3.u.i = (pIn3->flags & MEM_Null)==0; + pIn3 = &x3; }else{ - /* If the 0x200 bit of P1 is clear and either operand is NULL then - ** the result is always NULL. The jump is taken if the 0x100 bit - ** of P1 is set. + /* If the SQLITE_NULLEQUAL bit is clear and either operand is NULL then + ** the result is always NULL. The jump is taken if the + ** SQLITE_JUMPIFNULL bit is set. */ - popStack(&pTos, 2); - if( pOp->p2 ){ - if( pOp->p1 & 0x100 ){ - pc = pOp->p2-1; - } - }else{ - pTos++; - pTos->flags = MEM_Null; + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &p->aMem[pOp->p2]; + Release(pOut); + pOut->flags = MEM_Null; + REGISTER_TRACE(pOp->p2, pOut); + }else if( pOp->p5 & SQLITE_JUMPIFNULL ){ + pc = pOp->p2-1; } break; } } - affinity = pOp->p1 & 0xFF; + affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity ){ - applyAffinity(pNos, affinity, encoding); - applyAffinity(pTos, affinity, encoding); + applyAffinity(pIn1, affinity, encoding); + applyAffinity(pIn3, affinity, encoding); } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - ExpandBlob(pNos); - ExpandBlob(pTos); - res = sqlite3MemCompare(pNos, pTos, pOp->p4.pColl); + ExpandBlob(pIn1); + ExpandBlob(pIn3); + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; case OP_Ne: res = res!=0; break; @@ -1946,15 +1928,14 @@ case OP_Ge: { /* same as TK_GE, no-push, jump */ default: res = res>=0; break; } - popStack(&pTos, 2); - if( pOp->p2 ){ - if( res ){ - pc = pOp->p2-1; - } - }else{ - pTos++; - pTos->flags = MEM_Int; - pTos->u.i = res; + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &p->aMem[pOp->p2]; + Release(pOut); + pOut->flags = MEM_Int; + pOut->u.i = res; + REGISTER_TRACE(pOp->p2, pOut); + }else if( res ){ + pc = pOp->p2-1; } break; } diff --git a/src/vdbe.h b/src/vdbe.h index 33f091d805..d9665474dd 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.122 2008/01/03 11:50:30 danielk1977 Exp $ +** $Id: vdbe.h,v 1.123 2008/01/08 23:54:25 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -150,7 +150,7 @@ int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); -void sqlite3VdbeChangeP5(Vdbe*, int addr, u8 P5); +void sqlite3VdbeChangeP5(Vdbe*, u8 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 391b0d0dca..a8853f3ee0 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -411,12 +411,14 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ } /* -** Change the value of the P5 operand for a specific instruction. +** Change the value of the P5 operand for the most recently +** added operation. */ -void sqlite3VdbeChangeP5(Vdbe *p, int addr, u8 val){ +void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ assert( p==0 || p->magic==VDBE_MAGIC_INIT ); - if( p && addr>=0 && p->nOp>addr && p->aOp ){ - p->aOp[addr].p5 = val; + if( p && p->aOp ){ + assert( p->nOp>0 ); + p->aOp[p->nOp-1].p5 = val; } } diff --git a/src/where.c b/src/where.c index 4d9454fbbc..f5f86e9bd9 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.277 2008/01/07 19:20:25 drh Exp $ +** $Id: where.c,v 1.278 2008/01/08 23:54:26 drh Exp $ */ #include "sqliteInt.h" @@ -2024,7 +2024,7 @@ WhereInfo *sqlite3WhereBegin( ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ - sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); + sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); pWhere = 0; } @@ -2384,7 +2384,8 @@ WhereInfo *sqlite3WhereBegin( if( testOp!=OP_Noop ){ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); - sqlite3VdbeAddOp2(v, testOp, SQLITE_AFF_NUMERIC|0x100, brk); + sqlite3VdbeAddOp2(v, testOp, 0, brk); + sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLevel->flags & WHERE_COLUMN_RANGE ){ /* Case 3: The WHERE clause term that refers to the right-most @@ -2651,7 +2652,7 @@ WhereInfo *sqlite3WhereBegin( if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } - sqlite3ExprIfFalse(pParse, pE, cont, 1); + sqlite3ExprIfFalse(pParse, pE, cont, SQLITE_JUMPIFNULL); pTerm->flags |= TERM_CODED; } @@ -2666,7 +2667,7 @@ WhereInfo *sqlite3WhereBegin( if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; assert( pTerm->pExpr ); - sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, 1); + sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL); pTerm->flags |= TERM_CODED; } }