diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 164 | ||||
-rw-r--r-- | src/insert.c | 26 | ||||
-rw-r--r-- | src/select.c | 18 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/trigger.c | 2 | ||||
-rw-r--r-- | src/vdbe.c | 257 | ||||
-rw-r--r-- | src/vdbe.h | 97 | ||||
-rw-r--r-- | src/where.c | 6 |
8 files changed, 375 insertions, 201 deletions
diff --git a/src/expr.c b/src/expr.c index 94aa06df5..89508d26c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.63 2002/05/24 02:04:33 drh Exp $ +** $Id: expr.c,v 1.64 2002/05/26 20:54:33 drh Exp $ */ #include "sqliteInt.h" @@ -818,7 +818,13 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ case TK_REM: case TK_BITAND: case TK_BITOR: - case TK_SLASH: { + case TK_SLASH: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, 0); @@ -837,21 +843,6 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ sqliteVdbeAddOp(v, OP_Concat, 2, 0); break; } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - int dest; - sqliteVdbeAddOp(v, OP_Integer, 1, 0); - sqliteExprCode(pParse, pExpr->pLeft); - sqliteExprCode(pParse, pExpr->pRight); - dest = sqliteVdbeCurrentAddr(v) + 2; - sqliteVdbeAddOp(v, op, 0, dest); - sqliteVdbeAddOp(v, OP_AddImm, -1, 0); - break; - } case TK_UMINUS: { assert( pExpr->pLeft ); if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){ @@ -881,7 +872,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteExprCode(pParse, pExpr->pLeft); dest = sqliteVdbeCurrentAddr(v) + 2; - sqliteVdbeAddOp(v, op, 0, dest); + sqliteVdbeAddOp(v, op, 1, dest); sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } @@ -913,20 +904,27 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); + sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4); + sqliteVdbeAddOp(v, OP_Pop, 1, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0); + sqliteVdbeAddOp(v, OP_Goto, 0, addr+6); if( pExpr->pSelect ){ - sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+2); + sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6); }else{ - sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+2); + sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6); } sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_BETWEEN: { - int lbl = sqliteVdbeMakeLabel(v); - sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteExprIfFalse(pParse, pExpr, lbl); - sqliteVdbeAddOp(v, OP_AddImm, 1, 0); - sqliteVdbeResolveLabel(v, lbl); + sqliteExprCode(pParse, pExpr->pLeft); + sqliteVdbeAddOp(v, OP_Dup, 0, 0); + sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); + sqliteVdbeAddOp(v, OP_Ge, 0, 0); + sqliteVdbeAddOp(v, OP_Pull, 1, 0); + sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); + sqliteVdbeAddOp(v, OP_Le, 0, 0); + sqliteVdbeAddOp(v, OP_And, 0, 0); break; } case TK_AS: { @@ -935,44 +933,54 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ } case TK_CASE: { int expr_end_label; - int next_when_label; + int null_result_label; + int jumpInst; + int addr; + int nExpr; int i; assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); - expr_end_label = sqliteVdbeMakeLabel(pParse->pVdbe); + nExpr = pExpr->pList->nExpr; + expr_end_label = sqliteVdbeMakeLabel(v); + null_result_label = sqliteVdbeMakeLabel(v); if( pExpr->pLeft ){ sqliteExprCode(pParse, pExpr->pLeft); + sqliteVdbeAddOp(v, OP_IsNull, -1, expr_end_label); } - for(i=0; i<pExpr->pList->nExpr; i=i+2){ - if( i!=0 ){ - sqliteVdbeResolveLabel(pParse->pVdbe, next_when_label); - } - next_when_label = sqliteVdbeMakeLabel(pParse->pVdbe); + for(i=0; i<nExpr; i=i+2){ + sqliteExprCode(pParse, pExpr->pList->a[i].pExpr); + sqliteVdbeAddOp(v, OP_IsNull, -1, null_result_label); if( pExpr->pLeft ){ - sqliteVdbeAddOp(pParse->pVdbe, OP_Dup, 0, 1); - sqliteExprCode(pParse, pExpr->pList->a[i].pExpr); - sqliteVdbeAddOp(pParse->pVdbe, OP_Ne, 0, next_when_label); + sqliteVdbeAddOp(v, OP_Dup, 1, 1); + jumpInst = sqliteVdbeAddOp(v, OP_Ne, 0, 0); }else{ - sqliteExprIfFalse(pParse, pExpr->pList->a[i].pExpr, next_when_label); - } - if( pExpr->pLeft ){ - sqliteVdbeAddOp(pParse->pVdbe, OP_Pop, 1, 0); + jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 0, 0); } sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr); - sqliteVdbeAddOp(pParse->pVdbe, OP_Goto, 0, expr_end_label); - } - sqliteVdbeResolveLabel(pParse->pVdbe, next_when_label); - if( pExpr->pLeft ){ - sqliteVdbeAddOp(pParse->pVdbe, OP_Pop, 1, 0); + sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label); + if( i>=nExpr-2 ){ + sqliteVdbeResolveLabel(v, null_result_label); + sqliteVdbeAddOp(v, OP_Pop, 1, 0); + if( pExpr->pRight!=0 ){ + sqliteVdbeAddOp(v, OP_String, 0, 0); + sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label); + } + } + addr = sqliteVdbeCurrentAddr(v); + sqliteVdbeChangeP2(v, jumpInst, addr); } if( pExpr->pRight ){ sqliteExprCode(pParse, pExpr->pRight); }else{ - sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0); + } + sqliteVdbeResolveLabel(v, expr_end_label); + if( pExpr->pLeft ){ + sqliteVdbeAddOp(v, OP_Pull, 1, 0); + sqliteVdbeAddOp(v, OP_Pop, 1, 0); } - sqliteVdbeResolveLabel(pParse->pVdbe, expr_end_label); } break; } @@ -982,8 +990,11 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is true but execution ** 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. */ -void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){ +void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; @@ -1001,18 +1012,18 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){ switch( pExpr->op ){ case TK_AND: { int d2 = sqliteVdbeMakeLabel(v); - sqliteExprIfFalse(pParse, pExpr->pLeft, d2); - sqliteExprIfTrue(pParse, pExpr->pRight, dest); + sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_OR: { - sqliteExprIfTrue(pParse, pExpr->pLeft, dest); - sqliteExprIfTrue(pParse, pExpr->pRight, dest); + sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { - sqliteExprIfFalse(pParse, pExpr->pLeft, dest); + sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: @@ -1023,17 +1034,22 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){ case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); - sqliteVdbeAddOp(v, op, 0, dest); + sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 0, dest); + sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { + int addr; sqliteExprCode(pParse, pExpr->pLeft); + addr = sqliteVdbeCurrentAddr(v); + sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); + sqliteVdbeAddOp(v, OP_Pop, 1, 0); + sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest); }else{ @@ -1042,21 +1058,21 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){ break; } case TK_BETWEEN: { - int lbl = sqliteVdbeMakeLabel(v); + int addr; sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); - sqliteVdbeAddOp(v, OP_Lt, 0, lbl); + addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); - sqliteVdbeAddOp(v, OP_Le, 0, dest); + sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest); sqliteVdbeAddOp(v, OP_Integer, 0, 0); - sqliteVdbeResolveLabel(v, lbl); + sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); sqliteVdbeAddOp(v, OP_Pop, 1, 0); break; } default: { sqliteExprCode(pParse, pExpr); - sqliteVdbeAddOp(v, OP_If, 0, dest); + sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest); break; } } @@ -1066,8 +1082,11 @@ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){ ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is false but execution ** 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. */ -void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){ +void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; @@ -1084,19 +1103,19 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){ } switch( pExpr->op ){ case TK_AND: { - sqliteExprIfFalse(pParse, pExpr->pLeft, dest); - sqliteExprIfFalse(pParse, pExpr->pRight, dest); + sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqliteVdbeMakeLabel(v); - sqliteExprIfTrue(pParse, pExpr->pLeft, d2); - sqliteExprIfFalse(pParse, pExpr->pRight, dest); + sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_NOT: { - sqliteExprIfTrue(pParse, pExpr->pLeft, dest); + sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: @@ -1107,17 +1126,22 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){ case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); - sqliteVdbeAddOp(v, op, 0, dest); + sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); - sqliteVdbeAddOp(v, op, 0, dest); + sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { + int addr; sqliteExprCode(pParse, pExpr->pLeft); + addr = sqliteVdbeCurrentAddr(v); + sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); + sqliteVdbeAddOp(v, OP_Pop, 1, 0); + sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest); }else{ @@ -1131,17 +1155,17 @@ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); addr = sqliteVdbeCurrentAddr(v); - sqliteVdbeAddOp(v, OP_Ge, 0, addr+3); + sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, dest); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); - sqliteVdbeAddOp(v, OP_Gt, 0, dest); + sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest); break; } default: { sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(v, OP_Not, 0, 0); - sqliteVdbeAddOp(v, OP_If, 0, dest); + sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest); break; } } diff --git a/src/insert.c b/src/insert.c index 53c3e7696..1c9b9b4cb 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.58 2002/05/24 02:04:33 drh Exp $ +** $Id: insert.c,v 1.59 2002/05/26 20:54:33 drh Exp $ */ #include "sqliteInt.h" @@ -290,14 +290,12 @@ void sqliteInsert( if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); }else{ - int addr; sqliteExprCode(pParse, pList->a[keyColumn].pExpr); /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno ** to generate a unique primary key value. */ - addr = sqliteVdbeAddOp(v, OP_Dup, 0, 1); - sqliteVdbeAddOp(v, OP_NotNull, 0, addr+4); + sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } @@ -499,7 +497,7 @@ void sqliteGenerateConstraintChecks( int iCur; Index *pIdx; int seenReplace = 0; - int jumpInst; + int jumpInst1, jumpInst2; int contAddr; int hasTwoRecnos = (isUpdate && recnoChng); @@ -527,7 +525,7 @@ void sqliteGenerateConstraintChecks( onError = OE_Abort; } sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1); - addr = sqliteVdbeAddOp(v, OP_NotNull, 0, 0); + addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0); switch( onError ){ case OE_Rollback: case OE_Abort: @@ -565,14 +563,13 @@ void sqliteGenerateConstraintChecks( if( onError==OE_Default ) onError = OE_Abort; } if( onError!=OE_Replace ){ - int jumpInst2; if( isUpdate ){ sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); - jumpInst2 = sqliteVdbeAddOp(v, OP_Eq, 0, 0); + jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0); } sqliteVdbeAddOp(v, OP_Dup, nCol, 1); - jumpInst = sqliteVdbeAddOp(v, OP_NotExists, base, 0); + jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0); switch( onError ){ case OE_Rollback: case OE_Abort: @@ -588,9 +585,9 @@ void sqliteGenerateConstraintChecks( default: assert(0); } contAddr = sqliteVdbeCurrentAddr(v); - sqliteVdbeChangeP2(v, jumpInst, contAddr); + sqliteVdbeChangeP2(v, jumpInst2, contAddr); if( isUpdate ){ - sqliteVdbeChangeP2(v, jumpInst2, contAddr); + sqliteVdbeChangeP2(v, jumpInst1, contAddr); sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } @@ -609,7 +606,7 @@ void sqliteGenerateConstraintChecks( sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); } } - sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); + jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); onError = pIdx->onError; if( onError==OE_None ) continue; if( overrideError!=OE_Default ){ @@ -619,7 +616,7 @@ void sqliteGenerateConstraintChecks( if( onError==OE_Default ) onError = OE_Abort; } sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1); - jumpInst = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); + jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); switch( onError ){ case OE_Rollback: case OE_Abort: @@ -645,7 +642,8 @@ void sqliteGenerateConstraintChecks( default: assert(0); } contAddr = sqliteVdbeCurrentAddr(v); - sqliteVdbeChangeP2(v, jumpInst, contAddr); + sqliteVdbeChangeP2(v, jumpInst1, contAddr); + sqliteVdbeChangeP2(v, jumpInst2, contAddr); } } diff --git a/src/select.c b/src/select.c index e4117f9d6..3be8650ce 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.85 2002/05/25 00:18:21 drh Exp $ +** $Id: select.c,v 1.86 2002/05/26 20:54:34 drh Exp $ */ #include "sqliteInt.h" @@ -325,13 +325,12 @@ static int selectInnerLoop( ** and this row has been seen before, then do not make this row ** part of the result. */ - if( distinct>=0 ){ - int lbl = sqliteVdbeMakeLabel(v); + if( distinct>=0 && pEList && pEList->nExpr>0 ){ + sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7); sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); - sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl); + sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); - sqliteVdbeResolveLabel(v, lbl); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0); } @@ -359,8 +358,8 @@ static int selectInnerLoop( ** table iParm. */ if( eDest==SRT_Union ){ - sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); - sqliteVdbeAddOp(v, OP_String, iParm, 0); + sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 1); + sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); }else @@ -378,7 +377,7 @@ static int selectInnerLoop( ** the temporary table iParm. */ if( eDest==SRT_Except ){ - int addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); + int addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 1); sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3); sqliteVdbeAddOp(v, OP_Delete, iParm, 0); }else @@ -389,6 +388,7 @@ static int selectInnerLoop( */ if( eDest==SRT_Set ){ assert( nColumn==1 ); + sqliteVdbeAddOp(v, OP_IsNull, -1, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); }else @@ -1738,7 +1738,7 @@ int sqliteSelect( startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg); pParse->useAgg = 1; if( pHaving ){ - sqliteExprIfFalse(pParse, pHaving, startagg); + sqliteExprIfFalse(pParse, pHaving, startagg, 1); } if( selectInnerLoop(pParse, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, startagg, endagg) ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 77cfe6282..4fec92231 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.116 2002/05/25 00:18:21 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.117 2002/05/26 20:54:34 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -817,8 +817,8 @@ void sqliteUpdate(Parse*, Token*, ExprList*, Expr*, int); WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); -void sqliteExprIfTrue(Parse*, Expr*, int); -void sqliteExprIfFalse(Parse*, Expr*, int); +void sqliteExprIfTrue(Parse*, Expr*, int, int); +void sqliteExprIfFalse(Parse*, Expr*, int, int); Table *sqliteFindTable(sqlite*,const char*); Index *sqliteFindIndex(sqlite*,const char*); void sqliteUnlinkAndDeleteIndex(sqlite*,Index*); diff --git a/src/trigger.c b/src/trigger.c index 48e7ecf79..82ba258a0 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -587,7 +587,7 @@ int sqliteCodeRowTrigger( sqliteExprDelete(whenExpr); return 1; } - sqliteExprIfFalse(pParse, whenExpr, endTrigger); + sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1); sqliteExprDelete(whenExpr); codeTriggerProgram(pParse, pTrigger->step_list, orconf); diff --git a/src/vdbe.c b/src/vdbe.c index af42f9b52..fa558eb7c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.148 2002/05/24 20:31:37 drh Exp $ +** $Id: vdbe.c,v 1.149 2002/05/26 20:54:34 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1068,17 +1068,17 @@ static char *zOpName[] = { 0, "AggFunc", "AggInit", "AggPush", "AggPop", "SetInsert", "SetFound", "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey", "Goto", - "If", "Halt", "ColumnCount", "ColumnName", - "Callback", "NullCallback", "Integer", "String", - "Pop", "Dup", "Pull", "Push", - "MustBeInt", "Add", "AddImm", "Subtract", - "Multiply", "Divide", "Remainder", "BitAnd", - "BitOr", "BitNot", "ShiftLeft", "ShiftRight", - "AbsValue", "Eq", "Ne", "Lt", - "Le", "Gt", "Ge", "IsNull", - "NotNull", "Negative", "And", "Or", - "Not", "Concat", "Noop", "Function", - "Limit", + "If", "IfNot", "Halt", "ColumnCount", + "ColumnName", "Callback", "NullCallback", "Integer", + "String", "Pop", "Dup", "Pull", + "Push", "MustBeInt", "Add", "AddImm", + "Subtract", "Multiply", "Divide", "Remainder", + "BitAnd", "BitOr", "BitNot", "ShiftLeft", + "ShiftRight", "AbsValue", "Eq", "Ne", + "Lt", "Le", "Gt", "Ge", + "IsNull", "NotNull", "Negative", "And", + "Or", "Not", "Concat", "Noop", + "Function", "Limit", }; /* @@ -1280,6 +1280,7 @@ int sqliteVdbeExec( sqlite *db = p->db; /* The database */ char **zStack; /* Text stack */ Stack *aStack; /* Additional stack information */ + unsigned uniqueCnt = 0; /* Used by OP_MakeRecord when P2!=0 */ int errorAction = OE_Abort; /* Recovery action to do in case of an error */ int undoTransOnError = 0; /* If error, either ROLLBACK or COMMIT */ char zBuf[100]; /* Space to sprintf() an integer */ @@ -1719,6 +1720,7 @@ case OP_Concat: { ** 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. */ /* Opcode: Multiply * * * ** @@ -1726,6 +1728,7 @@ case OP_Concat: { ** 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 multiplication. +** If either operand is NULL, the result is NULL. */ /* Opcode: Subtract * * * ** @@ -1735,6 +1738,7 @@ case OP_Concat: { ** 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. */ /* Opcode: Divide * * * ** @@ -1744,6 +1748,7 @@ case OP_Concat: { ** 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. */ /* Opcode: Remainder * * * ** @@ -1753,6 +1758,7 @@ case OP_Concat: { ** 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. */ case OP_Add: case OP_Subtract: @@ -1762,7 +1768,11 @@ case OP_Remainder: { int tos = p->tos; int nos = tos - 1; VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( (aStack[tos].flags & aStack[nos].flags & STK_Int)==STK_Int ){ + if( ((aStack[tos].flags | aStack[nos].flags) & STK_Null)!=0 ){ + POPSTACK; + Release(p, nos); + aStack[nos].flags = STK_Null; + }else if( (aStack[tos].flags & aStack[nos].flags & STK_Int)==STK_Int ){ int a, b; a = aStack[tos].i; b = aStack[nos].i; @@ -1838,7 +1848,9 @@ case OP_Function: { VERIFY( if( n<0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) for(i=p->tos-n+1; i<=p->tos; i++){ - if( (aStack[i].flags & STK_Null)==0 ){ + if( aStack[i].flags & STK_Null ){ + zStack[i] = 0; + }else{ if( Stringify(p, i) ) goto no_mem; } } @@ -1872,24 +1884,28 @@ case OP_Function: { ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the bit-wise AND of the ** two elements. +** If either operand is NULL, the result is NULL. */ /* Opcode: BitOr * * * ** ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the bit-wise OR of the ** two elements. +** If either operand is NULL, the result is NULL. */ /* Opcode: ShiftLeft * * * ** ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the top element shifted ** left by N bits where N is the second element on the stack. +** If either operand is NULL, the result is NULL. */ /* Opcode: ShiftRight * * * ** ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the top element shifted ** right by N bits where N is the second element on the stack. +** If either operand is NULL, the result is NULL. */ case OP_BitAnd: case OP_BitOr: @@ -1899,6 +1915,12 @@ case OP_ShiftRight: { int nos = tos - 1; int a, b; VERIFY( if( nos<0 ) goto not_enough_stack; ) + if( (aStack[tos].flags | aStack[nos].flags) & STK_Null ){ + POPSTACK; + Release(p,nos); + aStack[nos].flags = STK_Null; + break; + } Integerify(p, tos); Integerify(p, nos); a = aStack[tos].i; @@ -1973,40 +1995,82 @@ mismatch: break; } -/* Opcode: Eq * P2 * +/* Opcode: Eq P1 P2 * ** ** Pop the top two elements from the stack. If they are equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ -/* Opcode: Ne * P2 * +/* Opcode: Ne P1 P2 * ** ** Pop the top two elements from the stack. If they are not equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ -/* Opcode: Lt * P2 * +/* Opcode: Lt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than the first (the top of stack), then ** jump to instruction P2. Otherwise, continue to the next instruction. ** In other words, jump if NOS<TOS. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ -/* Opcode: Le * P2 * +/* Opcode: Le P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS<=TOS. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ -/* Opcode: Gt * P2 * +/* Opcode: Gt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is greater than the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>TOS. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ -/* Opcode: Ge * P2 * +/* Opcode: Ge P1 P2 * ** ** Pop the top two elements from the stack. If second element (the next ** on stack) is greater than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>=TOS. +** +** If either operand is NULL (and thus if the result is unknown) then +** take the jump if P1 is true. +** +** If P2 is zero, do not jump. Instead, push an integer 1 onto the +** stack if the jump would have been taken, or a 0 if not. Push a +** NULL if either operand was NULL. */ case OP_Eq: case OP_Ne: @@ -2021,7 +2085,17 @@ case OP_Ge: { VERIFY( if( nos<0 ) goto not_enough_stack; ) ft = aStack[tos].flags; fn = aStack[nos].flags; - if( (ft & fn & STK_Int)==STK_Int ){ + if( (ft | fn) & STK_Null ){ + POPSTACK; + POPSTACK; + if( pOp->p2 ){ + if( pOp->p1 ) pc = pOp->p2-1; + }else{ + p->tos++; + aStack[nos].flags = STK_Null; + } + break; + }else if( (ft & fn & STK_Int)==STK_Int ){ c = aStack[nos].i - aStack[tos].i; }else if( (ft & STK_Int)!=0 && (fn & STK_Str)!=0 && isInteger(zStack[nos]) ){ Integerify(p, nos); @@ -2043,7 +2117,13 @@ case OP_Ge: { } POPSTACK; POPSTACK; - if( c ) pc = pOp->p2-1; + if( pOp->p2 ){ + if( c ) pc = pOp->p2-1; + }else{ + p->tos++; + aStack[nos].flags = STK_Int; + aStack[nos].i = c; + } break; } @@ -2052,12 +2132,14 @@ case OP_Ge: { ** Pop two values off the stack. Take the logical AND of the ** two values and push the resulting boolean value back onto the ** stack. +** If either operand is NULL, the result is NULL. */ /* Opcode: Or * * * ** ** Pop two values off the stack. Take the logical OR of the ** two values and push the resulting boolean value back onto the ** stack. +** If either operand is NULL, the result is NULL. */ case OP_And: case OP_Or: { @@ -2065,6 +2147,12 @@ case OP_Or: { int nos = tos - 1; int c; VERIFY( if( nos<0 ) goto not_enough_stack; ) + if( (aStack[tos].flags | aStack[nos].flags) & STK_Null ){ + POPSTACK; + Release(p, nos); + aStack[nos].flags = STK_Null; + break; + } Integerify(p, tos); Integerify(p, nos); if( pOp->opcode==OP_And ){ @@ -2082,12 +2170,14 @@ case OP_Or: { /* Opcode: Negative * * * ** ** Treat the top of the stack as a numeric quantity. Replace it -** with its additive inverse. +** 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. +** with its absolute value. If the top of the stack is NULL +** its value is unchanged. */ case OP_Negative: case OP_AbsValue: { @@ -2105,6 +2195,8 @@ case OP_AbsValue: { aStack[tos].i = -aStack[tos].i; } aStack[tos].flags = STK_Int; + }else if( aStack[tos].flags & STK_Null ){ + /* Do nothing */ }else{ Realify(p, tos); Release(p, tos); @@ -2119,11 +2211,13 @@ case OP_AbsValue: { /* Opcode: Not * * * ** ** Interpret the top of the stack as a boolean value. Replace it -** with its complement. +** with its complement. If the top of the stack is NULL its value +** is unchanged. */ case OP_Not: { int tos = p->tos; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) + if( aStack[tos].flags & STK_Null ) break; /* Do nothing to NULLs */ Integerify(p, tos); Release(p, tos); aStack[tos].i = !aStack[tos].i; @@ -2134,11 +2228,13 @@ case OP_Not: { /* Opcode: BitNot * * * ** ** Interpret the top of the stack as an value. Replace it -** with its ones-complement. +** with its ones-complement. If the top of the stack is NULL its +** value is unchanged. */ case OP_BitNot: { int tos = p->tos; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) + if( aStack[tos].flags & STK_Null ) break; /* Do nothing to NULLs */ Integerify(p, tos); Release(p, tos); aStack[tos].i = ~aStack[tos].i; @@ -2155,60 +2251,92 @@ case OP_Noop: { break; } -/* Opcode: If * P2 * +/* Opcode: If P1 P2 * ** ** Pop a single boolean from the stack. If the boolean popped is ** true, then jump to p2. Otherwise continue to the next instruction. ** An integer is false if zero and true otherwise. A string is ** 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 * +** +** Pop a single boolean from the stack. If the boolean popped is +** false, then jump to p2. Otherwise continue to the next instruction. +** An integer is false if zero and true otherwise. A string is +** 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: { +case OP_If: +case OP_IfNot: { int c; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - Integerify(p, p->tos); - c = aStack[p->tos].i; + if( aStack[p->tos].flags & STK_Null ){ + c = pOp->p1; + }else{ + Integerify(p, p->tos); + c = aStack[p->tos].i; + if( pOp->opcode==OP_IfNot ) c = !c; + } POPSTACK; if( c ) pc = pOp->p2-1; break; } -/* Opcode: IsNull * P2 * +/* Opcode: IsNull P1 P2 * ** -** Pop a single value from the stack. If the value popped is NULL -** then jump to p2. Otherwise continue to the next -** instruction. +** If any of the top abs(P1) values on the stack are NULL, then jump +** to P2. The stack is popped P1 times if P1>0. If P1<0 then all values +** are left unchanged on the stack. */ case OP_IsNull: { - int c; - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - c = (aStack[p->tos].flags & STK_Null)!=0; - POPSTACK; - if( c ) pc = pOp->p2-1; + int i, cnt; + cnt = pOp->p1; + if( cnt<0 ) cnt = -cnt; + VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; ) + for(i=0; i<cnt; i++){ + if( aStack[p->tos-i].flags & STK_Null ){ + pc = pOp->p2-1; + break; + } + } + if( pOp->p1>0 ) PopStack(p, cnt); break; } -/* Opcode: NotNull * P2 * +/* Opcode: NotNull P1 P2 * ** -** Pop a single value from the stack. If the value popped is not -** NULL, then jump to p2. Otherwise continue to the next -** instruction. +** Jump to P2 if the top value on the stack is not NULL. Pop the +** stack if P1 is greater than zero. If P1 is less than or equal to +** zero then leave the value on the stack. */ case OP_NotNull: { - int c; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - c = (aStack[p->tos].flags & STK_Null)==0; - POPSTACK; - if( c ) pc = pOp->p2-1; + if( (aStack[p->tos].flags & STK_Null)==0 ) pc = pOp->p2-1; + if( pOp->p1>0 ){ POPSTACK; } break; } -/* Opcode: MakeRecord P1 * * +/* Opcode: MakeRecord P1 P2 * ** ** Convert the top P1 entries of the stack into a single entry ** suitable for use as a data record in a database table. The ** details of the format are irrelavant as long as the OP_Column ** opcode can decode the record later. Refer to source code ** comments for the details of the record format. +** +** If P2 is true (non-zero) and one or more of the P1 entries +** that go into building the record is NULL, then add some extra +** bytes to the record to make it distinct for other entries created +** during the same run of the VDBE. The extra bytes added are a +** counter that is reset with each run of the VDBE, so records +** created this way will not necessarily be distinct across runs. +** But they should be distinct for transient tables (created using +** OP_OpenTemp) which is what they are intended for. */ case OP_MakeRecord: { char *zNewRecord; @@ -2217,6 +2345,8 @@ case OP_MakeRecord: { int i, j; int idxWidth; u32 addr; + int addUnique = 0; /* True to cause bytes to be added to make the + ** generated record distinct */ /* Assuming the record contains N fields, the record format looks ** like this: @@ -2240,11 +2370,14 @@ case OP_MakeRecord: { VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) nByte = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & STK_Null)==0 ){ + if( (aStack[i].flags & STK_Null) ){ + addUnique = pOp->p2; + }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } + if( addUnique ) nByte += sizeof(uniqueCnt); if( nByte + nField + 1 < 256 ){ idxWidth = 1; }else if( nByte + 2*nField + 2 < 65536 ){ @@ -2260,7 +2393,7 @@ case OP_MakeRecord: { zNewRecord = sqliteMalloc( nByte ); if( zNewRecord==0 ) goto no_mem; j = 0; - addr = idxWidth*(nField+1); + addr = idxWidth*(nField+1) + addUnique*sizeof(uniqueCnt); for(i=p->tos-nField+1; i<=p->tos; i++){ zNewRecord[j++] = addr & 0xff; if( idxWidth>1 ){ @@ -2280,6 +2413,11 @@ case OP_MakeRecord: { zNewRecord[j++] = (addr>>16)&0xff; } } + if( addUnique ){ + memcpy(&zNewRecord[j], &uniqueCnt, sizeof(uniqueCnt)); + uniqueCnt++; + j += sizeof(uniqueCnt); + } for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ memcpy(&zNewRecord[j], zStack[i], aStack[i].n); @@ -2311,7 +2449,7 @@ case OP_MakeRecord: { ** ** See also: MakeIdxKey, SortMakeKey */ -/* Opcode: MakeIdxKey P1 * * +/* Opcode: MakeIdxKey P1 P2 * ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. In addition, take one additional integer @@ -2327,6 +2465,12 @@ case OP_MakeRecord: { ** in the stack is the first field and the top of the stack becomes the ** last. ** +** If P2 is not zero and one or more of the P1 entries that go into the +** generated key is NULL, then jump to P2 after the new key has been +** pushed on the stack. In other words, jump to P2 if the key is +** guaranteed to be unique. This jump can be used to skip a subsequent +** uniqueness test. +** ** See also: MakeKey, SortMakeKey */ case OP_MakeIdxKey: @@ -2336,6 +2480,7 @@ case OP_MakeKey: { int nField; int addRowid; int i, j; + int containsNull = 0; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; @@ -2347,6 +2492,7 @@ case OP_MakeKey: { char *z; if( flags & STK_Null ){ nByte += 2; + containsNull = 1; }else if( flags & STK_Real ){ z = aStack[i].z; sqliteRealToSortable(aStack[i].r, &z[1]); @@ -2406,8 +2552,11 @@ case OP_MakeKey: { Integerify(p, p->tos-nField); iKey = intToKey(aStack[p->tos-nField].i); memcpy(&zNewKey[j], &iKey, sizeof(u32)); + PopStack(p, nField+1); + if( pOp->p2 && containsNull ) pc = pOp->p2 - 1; + }else{ + if( pOp->p2==0 ) PopStack(p, nField+addRowid); } - if( pOp->p2==0 ) PopStack(p, nField+addRowid); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].n = nByte; @@ -4373,7 +4522,9 @@ case OP_AggFunc: { VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; ) for(i=p->tos-n; i<p->tos; i++){ - if( (aStack[i].flags & STK_Null)==0 ){ + if( aStack[i].flags & STK_Null ){ + zStack[i] = 0; + }else{ if( Stringify(p, i) ) goto no_mem; } } diff --git a/src/vdbe.h b/src/vdbe.h index 23410437e..42e9a07b0 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.52 2002/05/23 22:07:03 drh Exp $ +** $Id: vdbe.h,v 1.53 2002/05/26 20:54:34 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -157,53 +157,54 @@ typedef struct VdbeOp VdbeOp; #define OP_Goto 76 #define OP_If 77 -#define OP_Halt 78 - -#define OP_ColumnCount 79 -#define OP_ColumnName 80 -#define OP_Callback 81 -#define OP_NullCallback 82 - -#define OP_Integer 83 -#define OP_String 84 -#define OP_Pop 85 -#define OP_Dup 86 -#define OP_Pull 87 -#define OP_Push 88 -#define OP_MustBeInt 89 - -#define OP_Add 90 -#define OP_AddImm 91 -#define OP_Subtract 92 -#define OP_Multiply 93 -#define OP_Divide 94 -#define OP_Remainder 95 -#define OP_BitAnd 96 -#define OP_BitOr 97 -#define OP_BitNot 98 -#define OP_ShiftLeft 99 -#define OP_ShiftRight 100 -#define OP_AbsValue 101 -#define OP_Eq 102 -#define OP_Ne 103 -#define OP_Lt 104 -#define OP_Le 105 -#define OP_Gt 106 -#define OP_Ge 107 -#define OP_IsNull 108 -#define OP_NotNull 109 -#define OP_Negative 110 -#define OP_And 111 -#define OP_Or 112 -#define OP_Not 113 -#define OP_Concat 114 -#define OP_Noop 115 -#define OP_Function 116 - -#define OP_Limit 117 - - -#define OP_MAX 117 +#define OP_IfNot 78 +#define OP_Halt 79 + +#define OP_ColumnCount 80 +#define OP_ColumnName 81 +#define OP_Callback 82 +#define OP_NullCallback 83 + +#define OP_Integer 84 +#define OP_String 85 +#define OP_Pop 86 +#define OP_Dup 87 +#define OP_Pull 88 +#define OP_Push 89 +#define OP_MustBeInt 90 + +#define OP_Add 91 +#define OP_AddImm 92 +#define OP_Subtract 93 +#define OP_Multiply 94 +#define OP_Divide 95 +#define OP_Remainder 96 +#define OP_BitAnd 97 +#define OP_BitOr 98 +#define OP_BitNot 99 +#define OP_ShiftLeft 100 +#define OP_ShiftRight 101 +#define OP_AbsValue 102 +#define OP_Eq 103 +#define OP_Ne 104 +#define OP_Lt 105 +#define OP_Le 106 +#define OP_Gt 107 +#define OP_Ge 108 +#define OP_IsNull 109 +#define OP_NotNull 110 +#define OP_Negative 111 +#define OP_And 112 +#define OP_Or 113 +#define OP_Not 114 +#define OP_Concat 115 +#define OP_Noop 116 +#define OP_Function 117 + +#define OP_Limit 118 + + +#define OP_MAX 118 /* ** Prototypes for the VDBE interface. See comments on the implementation diff --git a/src/where.c b/src/where.c index a3576cae4..0f14df9de 100644 --- a/src/where.c +++ b/src/where.c @@ -13,7 +13,7 @@ ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** -** $Id: where.c,v 1.47 2002/05/24 20:31:38 drh Exp $ +** $Id: where.c,v 1.48 2002/05/26 20:54:34 drh Exp $ */ #include "sqliteInt.h" @@ -199,7 +199,7 @@ WhereInfo *sqliteWhereBegin( ** expression and either jump over all of the code or fall thru. */ if( pWhere && sqliteExprIsConstant(pWhere) ){ - sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak); + sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); } /* Split the WHERE clause into as many as 32 separate subexpressions @@ -795,7 +795,7 @@ WhereInfo *sqliteWhereBegin( haveKey = 0; sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); } - sqliteExprIfFalse(pParse, aExpr[j].p, cont); + sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1); aExpr[j].p = 0; } brk = cont; |