More changes to support the new types model. Compound SELECTs are currently
broken. (CVS 1389)

FossilOrigin-Name: 0f6c9b05e688e281fa168aacdd867db408df2863
diff --git a/src/expr.c b/src/expr.c
index 1ba427e..be2c265 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,11 +12,39 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.120 2004/05/16 22:55:28 danielk1977 Exp $
+** $Id: expr.c,v 1.121 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
 
+char const *sqlite3AffinityString(char affinity){
+  switch( affinity ){
+    case SQLITE_AFF_INTEGER: return "i";
+    case SQLITE_AFF_NUMERIC: return "n";
+    case SQLITE_AFF_TEXT:    return "t";
+    case SQLITE_AFF_NONE:    return "o";
+    default:
+      assert(0);
+  }
+}
+
+
+/*
+** Return the 'affinity' of the expression pExpr if any.
+**
+** If pExpr is a column, a reference to a column via an 'AS' alias,
+** or a sub-select with a column as the return value, then the 
+** affinity of that column is returned. Otherwise, 0x00 is returned,
+** indicating no affinity for the expression.
+**
+** i.e. the WHERE clause expresssions in the following statements all
+** have an affinity:
+**
+** CREATE TABLE t1(a);
+** SELECT * FROM t1 WHERE a;
+** SELECT a AS b FROM t1 WHERE b;
+** SELECT * FROM t1 WHERE (select a from t1);
+*/
 static char exprAffinity(Expr *pExpr){
   if( pExpr->op==TK_AS ){
     return exprAffinity(pExpr->pLeft);
@@ -27,6 +55,64 @@
   return pExpr->affinity;
 }
 
+char sqlite3CompareAffinity(Expr *pExpr, char aff2){
+  char aff1 = exprAffinity(pExpr);
+  if( aff1 && aff2 ){
+    /* Both sides of the comparison are columns. If one has numeric or
+    ** integer affinity, use that. Otherwise use no affinity.
+    */
+    if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){
+      return SQLITE_AFF_INTEGER;
+    }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){
+      return SQLITE_AFF_NUMERIC;
+    }else{
+      return SQLITE_AFF_NONE;
+    }
+  }else if( !aff1 && !aff2 ){
+    /* Neither side of the comparison is a column. Use numeric affinity
+    ** for the comparison.
+    */
+    return SQLITE_AFF_NUMERIC;
+  }else{
+    /* One side is a column, the other is not. Use the columns affinity. */
+    return (aff1 + aff2);
+  }
+}
+
+static char comparisonAffinity(Expr *pExpr){
+  char aff;
+  assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
+          pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
+          pExpr->op==TK_NE );
+  assert( pExpr->pLeft );
+  aff = exprAffinity(pExpr->pLeft);
+  if( pExpr->pRight ){
+    aff = sqlite3CompareAffinity(pExpr->pRight, aff);
+  }
+  else if( pExpr->pSelect ){
+    aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff);
+  }
+  else if( !aff ){
+    aff = SQLITE_AFF_NUMERIC;
+  }
+  return aff;
+}
+
+/*
+** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
+** idx_affinity is the affinity of an indexed column. Return true
+** if the index with affinity idx_affinity may be used to implement
+** the comparison in pExpr.
+*/
+int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
+  char aff = comparisonAffinity(pExpr);
+  return 
+    (aff==SQLITE_AFF_NONE) ||
+    (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) ||
+    (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) ||
+    (aff==idx_affinity);
+}
+
 /*
 ** Return the P1 value that should be used for a binary comparison
 ** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
@@ -34,27 +120,9 @@
 ** P1 value to tell the opcode to jump if either expression
 ** evaluates to NULL.
 */
-int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
-  char aff1 = exprAffinity(pExpr1);
-  char aff2 = exprAffinity(pExpr2);
-
-  if( aff1 && aff2 ){
-    /* Both sides of the comparison are columns. If one has numeric or
-    ** integer affinity, use that. Otherwise use no affinity.
-    */
-    if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){
-      aff1 = SQLITE_AFF_INTEGER;
-    }else
-    if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){
-      aff1 = SQLITE_AFF_NUMERIC;
-    }else{
-      aff1 = SQLITE_AFF_NONE;
-    }
-  }else if( !aff1 ){
-    aff1 = aff2;
-  }
-
-  return (((int)aff1)<<8)+(jumpIfNull?1:0);
+static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
+  char aff = exprAffinity(pExpr2);
+  return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0);
 }
 
 /*
@@ -728,30 +796,59 @@
     }
 
     case TK_IN: {
+      char affinity;
       Vdbe *v = sqlite3GetVdbe(pParse);
       if( v==0 ) return 1;
       if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
         return 1;
       }
+      affinity = exprAffinity(pExpr->pLeft);
+
+      /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
+      ** expression it is handled the same way. A temporary table is 
+      ** filled with single-field index keys representing the results
+      ** from the SELECT or the <exprlist>.
+      **
+      ** If the 'x' expression is a column value, or the SELECT...
+      ** statement returns a column value, then the affinity of that
+      ** column is used to build the index keys. If both 'x' and the
+      ** SELECT... statement are columns, then numeric affinity is used
+      ** if either column has NUMERIC or INTEGER affinity. If neither
+      ** 'x' nor the SELECT... statement are columns, then numeric affinity
+      ** is used.
+      */
+      pExpr->iTable = pParse->nTab++;
+      sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
+
       if( pExpr->pSelect ){
         /* Case 1:     expr IN (SELECT ...)
         **
-        ** Generate code to write the results of the select into a temporary
-        ** table.  The cursor number of the temporary table has already
-        ** been put in iTable by sqlite3ExprResolveInSelect().
+        ** Generate code to write the results of the select into the temporary
+        ** table allocated and opened above.
         */
-        pExpr->iTable = pParse->nTab++;
-        sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
-        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
+        int iParm = pExpr->iTable +  (((int)affinity)<<16);
+        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
+        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0);
       }else if( pExpr->pList ){
         /* Case 2:     expr IN (exprlist)
         **
-        ** Create a set to put the exprlist values in.  The Set id is stored
-        ** in iTable.
+	** For each expression, build an index key from the evaluation and
+        ** store it in the temporary table. If <expr> is a column, then use
+        ** that columns affinity when building index keys. If <expr> is not
+        ** a column, use numeric affinity.
         */
-        int i, iSet;
+        int i;
+        char const *affStr;
+        if( !affinity ){
+          affinity = SQLITE_AFF_NUMERIC;
+        }
+        affStr = sqlite3AffinityString(affinity);
+
+        /* Loop through each expression in <exprlist>. */
         for(i=0; i<pExpr->pList->nExpr; i++){
           Expr *pE2 = pExpr->pList->a[i].pExpr;
+
+          /* Check that the expression is constant and valid. */
           if( !sqlite3ExprIsConstant(pE2) ){
             sqlite3ErrorMsg(pParse,
               "right-hand side of IN operator must be constant");
@@ -760,27 +857,12 @@
           if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){
             return 1;
           }
-        }
-        iSet = pExpr->iTable = pParse->nSet++;
-        for(i=0; i<pExpr->pList->nExpr; i++){
-          Expr *pE2 = pExpr->pList->a[i].pExpr;
-          switch( pE2->op ){
-            case TK_FLOAT:
-            case TK_INTEGER:
-            case TK_STRING: {
-              int addr;
-              assert( pE2->token.z );
-              addr = sqlite3VdbeOp3(v, OP_SetInsert, iSet, 0,
-                                  pE2->token.z, pE2->token.n);
-              sqlite3VdbeDequoteP3(v, addr);
-              break;
-            }
-            default: {
-              sqlite3ExprCode(pParse, pE2);
-              sqlite3VdbeAddOp(v, OP_SetInsert, iSet, 0);
-              break;
-            }
-          }
+
+          /* Evaluate the expression and insert it into the temp table */
+          sqlite3ExprCode(pParse, pE2);
+          sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC);
+          sqlite3VdbeAddOp(v, OP_String, 0, 0);
+          sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0);
         }
       }
       break;
@@ -1127,12 +1209,6 @@
       sqlite3ExprCode(pParse, pExpr->pRight);
       sqlite3VdbeAddOp(v, op, p1, 0);
       break;
-#if 0
-      if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
-        op += 6;  /* Convert numeric opcodes to text opcodes */
-      }
-      /* Fall through into the next case */
-#endif
     }
     case TK_AND:
     case TK_OR:
@@ -1225,19 +1301,29 @@
     }
     case TK_IN: {
       int addr;
+      char const *affStr;
+
+      /* Figure out the affinity to use to create a key from the results
+      ** of the expression. affinityStr stores a static string suitable for
+      ** P3 of OP_MakeKey.
+      */
+      affStr = sqlite3AffinityString(comparisonAffinity(pExpr));
+
       sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
+
+      /* Code the <expr> from "<expr> IN (...)". The temporary table
+      ** pExpr->iTable contains the values that make up the (...) set.
+      */
       sqlite3ExprCode(pParse, pExpr->pLeft);
       addr = sqlite3VdbeCurrentAddr(v);
-      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4);
+      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4);            /* addr + 0 */
       sqlite3VdbeAddOp(v, OP_Pop, 2, 0);
       sqlite3VdbeAddOp(v, OP_String, 0, 0);
-      sqlite3VdbeAddOp(v, OP_Goto, 0, addr+6);
-      if( pExpr->pSelect ){
-        sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+6);
-      }else{
-        sqlite3VdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6);
-      }
-      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
+      sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7);
+      sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC); /* addr + 4 */
+      sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);
+      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);                  /* addr + 6 */
+
       break;
     }
     case TK_BETWEEN: {
@@ -1407,6 +1493,7 @@
       sqlite3VdbeAddOp(v, op, 1, dest);
       break;
     }
+#if 0
     case TK_IN: {
       int addr;
       sqlite3ExprCode(pParse, pExpr->pLeft);
@@ -1421,6 +1508,7 @@
       }
       break;
     }
+#endif
     case TK_BETWEEN: {
       int addr;
       sqlite3ExprCode(pParse, pExpr->pLeft);
@@ -1500,6 +1588,7 @@
       sqlite3VdbeAddOp(v, op, 1, dest);
       break;
     }
+#if 0
     case TK_IN: {
       int addr;
       sqlite3ExprCode(pParse, pExpr->pLeft);
@@ -1514,6 +1603,7 @@
       }
       break;
     }
+#endif
     case TK_BETWEEN: {
       int addr;
       sqlite3ExprCode(pParse, pExpr->pLeft);
diff --git a/src/insert.c b/src/insert.c
index a3c12ed..fd73dbb 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.99 2004/05/16 11:15:38 danielk1977 Exp $
+** $Id: insert.c,v 1.100 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -30,12 +30,12 @@
 */
 void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
   if( !pIdx->zColAff ){
-    /* The first time a column affinity string for a particular table is
+    /* The first time a column affinity string for a particular index is
     ** required, it is allocated and populated here. It is then stored as
-    ** a member of the Table structure for subsequent use.
+    ** a member of the Index structure for subsequent use.
     **
     ** The column affinity string will eventually be deleted by
-    ** sqliteDeleteIndex() when the Table structure itself is cleaned
+    ** sqliteDeleteIndex() when the Index structure itself is cleaned
     ** up.
     */
     int n;
diff --git a/src/select.c b/src/select.c
index 475a0fd..c4e5d1e 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.164 2004/05/11 06:55:14 danielk1977 Exp $
+** $Id: select.c,v 1.165 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -479,6 +479,7 @@
     case SRT_Set: {
       int addr1 = sqlite3VdbeCurrentAddr(v);
       int addr2;
+
       assert( nColumn==1 );
       sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
@@ -486,8 +487,13 @@
       if( pOrderBy ){
         pushOntoSorter(pParse, v, pOrderBy);
       }else{
+        char const *affStr;
+        char aff = (iParm>>16)&0xFF;
+        aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff);
+        affStr = sqlite3AffinityString(aff);
+        sqlite3VdbeOp3(v, OP_MakeKey, 1, 1, affStr, P3_STATIC);
         sqlite3VdbeAddOp(v, OP_String, 0, 0);
-        sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0);
+        sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
       }
       sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));
       break;
@@ -593,8 +599,9 @@
       sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
       sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
+      sqlite3VdbeOp3(v, OP_MakeKey, 1, 1, "n", P3_STATIC);
       sqlite3VdbeAddOp(v, OP_String, 0, 0);
-      sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0);
+      sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
       break;
     }
     case SRT_Mem: {
@@ -799,7 +806,7 @@
           char zBuf[30];
           sprintf(zBuf,"_%d",++cnt);
           n = strlen(zBuf);
-          sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0);
+          sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf,n,0);
           j = -1;
         }
       }
@@ -810,6 +817,9 @@
       sprintf(zBuf, "column%d", i+1);
       pTab->aCol[i].zName = sqliteStrDup(zBuf);
     }
+    
+    /* Affinity is always NONE, as there is no type name. */
+    pTab->aCol[i].affinity = SQLITE_AFF_NONE;
   }
   pTab->iPKey = -1;
   return pTab;
@@ -1942,7 +1952,7 @@
 **
 **     SRT_Mem         Store first result in memory cell iParm
 **
-**     SRT_Set         Store results as keys of a table with cursor iParm
+**     SRT_Set         Store results as keys of table iParm.
 **
 **     SRT_Union       Store results as a key in a temporary table iParm
 **
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index ee88619..29aac80 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.234 2004/05/16 11:15:39 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.235 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -1306,4 +1306,6 @@
 char sqlite3AffinityType(const char *, int);
 void sqlite3IndexAffinityStr(Vdbe *, Index *);
 void sqlite3TableAffinityStr(Vdbe *, Table *);
-
+char sqlite3CompareAffinity(Expr *pExpr, char aff2);
+char const *sqlite3AffinityString(char affinity);
+int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
diff --git a/src/vdbe.c b/src/vdbe.c
index a66a291..0126b9c 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.295 2004/05/16 11:57:28 danielk1977 Exp $
+** $Id: vdbe.c,v 1.296 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1379,16 +1379,10 @@
 ** operand is NULL (and thus if the result is unknown) then take the jump
 ** only if the least significant byte of P1 is 0x01.
 **
-** The second least significant byte of P1 determines whether any
-** conversions are applied to the two values before the comparison is made.
-** If this byte is 0x00, and one of the values being compared is numeric
-** and the other text, an attempt is made to convert the text value to 
-** a numeric form.
-**
-** If the second least significant byte of P1 is not 0x00, then it must
-** be an affinity character - 'n', 't', 'i' or 'o'. In this case an 
-** attempt is made to coerce both values according to the affinity before
-** the comparison is made.
+** The second least significant byte of P1 must be an affinity character -
+** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
+** according to the affinity before the comparison is made. If the byte is
+** 0x00, then numeric affinity is used.
 **
 ** Once any conversions have taken place, and neither value is NULL, 
 ** the values are compared. If both values are blobs, or both are text,
@@ -1527,13 +1521,9 @@
   }
 
   affinity = (pOp->p1>>8)&0xFF;
-  if( !affinity && (flags&(MEM_Real|MEM_Int)) ){
-    affinity = SQLITE_AFF_NUMERIC;
-  }
-  if( affinity ){
-    applyAffinity(pNos, affinity);
-    applyAffinity(pTos, affinity);
-  }
+  if( affinity=='\0' ) affinity = 'n';
+  applyAffinity(pNos, affinity);
+  applyAffinity(pTos, affinity);
 
   res = sqlite3MemCompare(pNos, pTos);
   switch( pOp->opcode ){
@@ -2401,11 +2391,7 @@
   */
   for(pRec=pData0; pRec<=pTos; pRec++){
     u64 serial_type;
-    if( zAffinity ){
-      applyAffinity(pRec, zAffinity[pRec-pData0]);
-    }else{
-      applyAffinity(pRec, SQLITE_SO_NUM);
-    }
+    applyAffinity(pRec, zAffinity[pRec-pData0]);
     if( pRec->flags&MEM_Null ){
       containsNull = 1;
     }
@@ -2837,7 +2823,8 @@
       rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); 
       if( rc==SQLITE_OK ){
         assert( pgno==MASTER_ROOT+1 );
-        rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, 0, 0, &pCx->pCursor);
+        rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeKeyCompare,
+            pCx, &pCx->pCursor);
       }
     }else{
       rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor);
@@ -3546,6 +3533,57 @@
   break;
 }
 
+/* Opcode: IdxColumn P1 * *
+**
+** P1 is a cursor opened on an index. Push the first field from the
+** current index key onto the stack.
+*/
+case OP_IdxColumn: {
+  char *zData;
+  i64 n;
+  u64 serial_type;
+  int len;
+  int freeZData = 0;
+  BtCursor *pCsr;
+
+  assert( 0==p->apCsr[pOp->p1]->intKey );
+  pCsr = p->apCsr[pOp->p1]->pCursor;
+  rc = sqlite3BtreeKeySize(pCsr, &n);
+  if( rc!=SQLITE_OK ){
+    goto abort_due_to_error;
+  }
+  if( n>10 ) n = 10;
+
+  zData = (char *)sqlite3BtreeKeyFetch(pCsr, n);
+  assert( zData );
+
+  len = sqlite3GetVarint(zData, &serial_type);
+  n = sqlite3VdbeSerialTypeLen(serial_type);
+
+  zData = (char *)sqlite3BtreeKeyFetch(pCsr, len+n);
+  if( !zData ){
+    zData = (char *)sqliteMalloc(n);
+    if( !zData ){
+      rc = SQLITE_NOMEM;
+      goto abort_due_to_error;
+    }
+    rc = sqlite3BtreeKey(pCsr, len, n, zData);
+    if( rc!=SQLITE_OK ){
+      sqliteFree(zData);
+      goto abort_due_to_error;
+    }
+    freeZData = 1;
+    len = 0;
+  }
+
+  pTos++;
+  sqlite3VdbeSerialGet(&zData[len], serial_type, pTos);
+  if( freeZData ){
+    sqliteFree(zData);
+  }
+  break;
+}
+
 /* Opcode: FullKey P1 * *
 **
 ** Extract the complete key from the record that cursor P1 is currently
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 80a0f9a..e88341e 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1458,8 +1458,6 @@
     return -1;
   }
 
-return_result:
-
   return 0;
 }
 
diff --git a/src/where.c b/src/where.c
index aa3f328..e65362e 100644
--- a/src/where.c
+++ b/src/where.c
@@ -12,7 +12,7 @@
 ** This module contains C code that generates VDBE code used to process
 ** the WHERE clause of SQL statements.
 **
-** $Id: where.c,v 1.94 2004/05/16 11:15:41 danielk1977 Exp $
+** $Id: where.c,v 1.95 2004/05/17 10:48:58 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -536,8 +536,10 @@
              && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
           int iColumn = aExpr[j].p->pLeft->iColumn;
           int k;
+          char idxaff = pIdx->pTable->aCol[iColumn].affinity; 
           for(k=0; k<pIdx->nColumn; k++){
-            if( pIdx->aiColumn[k]==iColumn ){
+            if( pIdx->aiColumn[k]==iColumn 
+                && sqlite3IndexAffinityOk(aExpr[j].p, idxaff) ){
               switch( aExpr[j].p->op ){
                 case TK_IN: {
                   if( k==0 ) inMask |= 1;
@@ -571,8 +573,10 @@
              && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
           int iColumn = aExpr[j].p->pRight->iColumn;
           int k;
+          char idxaff = pIdx->pTable->aCol[iColumn].affinity; 
           for(k=0; k<pIdx->nColumn; k++){
-            if( pIdx->aiColumn[k]==iColumn ){
+            if( pIdx->aiColumn[k]==iColumn 
+                && sqlite3IndexAffinityOk(aExpr[j].p, idxaff) ){
               switch( aExpr[j].p->op ){
                 case TK_EQ: {
                   eqMask |= 1<<k;
@@ -720,16 +724,10 @@
         Expr *pX = aExpr[k].p;
         if( pX->op!=TK_IN ){
           sqlite3ExprCode(pParse, aExpr[k].p->pRight);
-        }else if( pX->pList ){
-          sqlite3VdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
-          pLevel->inOp = OP_SetNext;
-          pLevel->inP1 = pX->iTable;
-          pLevel->inP2 = sqlite3VdbeCurrentAddr(v);
         }else{
-          assert( pX->pSelect );
           sqlite3VdbeAddOp(v, OP_Rewind, pX->iTable, brk);
           sqlite3VdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
-          pLevel->inP2 = sqlite3VdbeAddOp(v, OP_FullKey, pX->iTable, 0);
+          pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0);
           pLevel->inOp = OP_Next;
           pLevel->inP1 = pX->iTable;
         }
@@ -758,27 +756,22 @@
              && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
              && pX->pLeft->iColumn==pIdx->aiColumn[j]
           ){
-            if( pX->op==TK_EQ ){
-              sqlite3ExprCode(pParse, pX->pRight);
-              aExpr[k].p = 0;
-              break;
-            }
-            if( pX->op==TK_IN && nColumn==1 ){
-              if( pX->pList ){
-                sqlite3VdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
-                pLevel->inOp = OP_SetNext;
-                pLevel->inP1 = pX->iTable;
-                pLevel->inP2 = sqlite3VdbeCurrentAddr(v);
-              }else{
-                assert( pX->pSelect );
+            char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity;
+            if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
+              if( pX->op==TK_EQ ){
+                sqlite3ExprCode(pParse, pX->pRight);
+                aExpr[k].p = 0;
+                break;
+              }
+              if( pX->op==TK_IN && nColumn==1 ){
                 sqlite3VdbeAddOp(v, OP_Rewind, pX->iTable, brk);
                 sqlite3VdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
-                pLevel->inP2 = sqlite3VdbeAddOp(v, OP_FullKey, pX->iTable, 0);
+                pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0);
                 pLevel->inOp = OP_Next;
                 pLevel->inP1 = pX->iTable;
+                aExpr[k].p = 0;
+                break;
               }
-              aExpr[k].p = 0;
-              break;
             }
           }
           if( aExpr[k].idxRight==iCur
@@ -786,9 +779,12 @@
              && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
              && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
           ){
-            sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
-            aExpr[k].p = 0;
-            break;
+            char idxaff = pIdx->pTable->aCol[pX->pRight->iColumn].affinity;
+            if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
+              sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
+              aExpr[k].p = 0;
+              break;
+            }
           }
         }
       }