NULL values are distinct.  A comparison involving a NULL is always false.
Operations on a NULL value yield a NULL result.  This change makes SQLite
operate more like the SQL spec, but it may break existing applications that
assumed the old behavior.  All the old tests pass but we still need to add
new tests to better verify the new behavior.  Fix for ticket #44. (CVS 589)

FossilOrigin-Name: 9051173742f1b0e15a809d12a0c9c98fd2c4614d
diff --git a/src/expr.c b/src/expr.c
index 94aa06d..89508d2 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 @@
     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 @@
       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 @@
       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 @@
       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 @@
     }
     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(pParse->pVdbe, expr_end_label);
+      sqliteVdbeResolveLabel(v, expr_end_label);
+      if( pExpr->pLeft ){
+        sqliteVdbeAddOp(v, OP_Pull, 1, 0);
+        sqliteVdbeAddOp(v, OP_Pop, 1, 0);
+      }
     }
     break;
   }
@@ -982,8 +990,11 @@
 ** 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 @@
   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 @@
     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 @@
       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 @@
 ** 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 @@
   }
   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 @@
     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 @@
       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 53c3e76..1c9b9b4 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 @@
       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 @@
   int iCur;
   Index *pIdx;
   int seenReplace = 0;
-  int jumpInst;
+  int jumpInst1, jumpInst2;
   int contAddr;
   int hasTwoRecnos = (isUpdate && recnoChng);
 
@@ -527,7 +525,7 @@
       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 @@
       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 @@
         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 @@
         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 @@
       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 @@
       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 e4117f9..3be8650 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 @@
   ** 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 @@
   ** 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 @@
   ** 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 @@
   */
   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 @@
     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 77cfe62..4fec922 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 @@
 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 48e7ecf..82ba258 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -587,7 +587,7 @@
         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 af42f9b..fa558eb 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 @@
   "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 @@
   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 @@
 ** 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 @@
 ** 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 @@
 ** 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 @@
 ** 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 @@
 ** 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 @@
   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 @@
   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 @@
 ** 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 @@
   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 @@
   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 @@
   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 @@
   }
   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 @@
 ** 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 @@
   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 @@
 /* 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 @@
       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 @@
 /* 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 @@
 /* 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 @@
   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.
 */
-case OP_If: {
+/* 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_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 @@
   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 @@
   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 @@
   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 @@
       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 @@
 **
 ** 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 @@
 ** 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 @@
   int nField;
   int addRowid;
   int i, j;
+  int containsNull = 0;
 
   addRowid = pOp->opcode==OP_MakeIdxKey;
   nField = pOp->p1;
@@ -2347,6 +2492,7 @@
     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 @@
     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 @@
   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 2341043..42e9a07 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 @@
 
 #define OP_Goto               76
 #define OP_If                 77
-#define OP_Halt               78
+#define OP_IfNot              78
+#define OP_Halt               79
 
-#define OP_ColumnCount        79
-#define OP_ColumnName         80
-#define OP_Callback           81
-#define OP_NullCallback       82
+#define OP_ColumnCount        80
+#define OP_ColumnName         81
+#define OP_Callback           82
+#define OP_NullCallback       83
 
-#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_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                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_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             117
+#define OP_Limit             118
 
 
-#define OP_MAX               117
+#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 a3576ca..0f14df9 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 @@
   ** 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 @@
         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;