]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Merge all changes from trunk.
authordrh <drh@noemail.net>
Wed, 12 Jun 2013 17:17:45 +0000 (17:17 +0000)
committerdrh <drh@noemail.net>
Wed, 12 Jun 2013 17:17:45 +0000 (17:17 +0000)
FossilOrigin-Name: f2e15b1974e55373b5819e3b2326653f890f409f

1  2 
manifest
manifest.uuid
src/build.c
src/where.c

diff --cc manifest
index 8b92ace17810e7ab0ea06f4759ed9cf635242971,dbb20a50de271635f11993f8a4735df21d28984b..4944aabb1c60d72fb958426f9efaeb3eb3183c78
+++ b/manifest
@@@ -1,5 -1,5 +1,5 @@@
- C "make\stest"\snow\spassing.
- D 2013-06-12T17:08:06.018
 -C Add\sthe\sSQLITE_FTS3_MAX_EXPR_DEPTH\scompile\stime\soption.
 -D 2013-06-11T14:22:11.456
++C Merge\sall\schanges\sfrom\strunk.
++D 2013-06-12T17:17:45.907
  F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
  F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
  F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@@ -78,11 -78,11 +78,11 @@@ F ext/fts3/README.content fdc666a70d525
  F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
  F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
  F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
 -F ext/fts3/fts3.c 931b3c83abdd1ab3bb389b2130431c2a9ff73b91
 +F ext/fts3/fts3.c 760fecd100598dc22f9733d472b7cf2e9375c620
  F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
- F ext/fts3/fts3Int.h 0b167bed9e63151635620a4f639bc62ac6012cba
+ F ext/fts3/fts3Int.h cb4df04cf886d9920a71df9e8faaa5aae2fa48c6
  F ext/fts3/fts3_aux.c b02632f6dd0e375ce97870206d914ea6d8df5ccd
- F ext/fts3/fts3_expr.c 193d6fc156d744ab548a2ed06c31869e54dac739
+ F ext/fts3/fts3_expr.c f8eb1046063ba342c7114eba175cabb31c4a64e7
  F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
  F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
  F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
@@@ -165,7 -165,7 +165,7 @@@ F src/btmutex.c 976f45a12e37293e32cae02
  F src/btree.c 7fba377c29573adfc6091832e27ee1fcbefb51d0
  F src/btree.h 6fa8a3ff2483d0bb64a9f0105a8cedeac9e00cca
  F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
- F src/build.c 838cbdcbf18de2fd5723ad5864a78cc806f6c75b
 -F src/build.c 1ecf68522356a90471b07178e186277090d0b027
++F src/build.c eadda12ec0cae14dcdc13e97fd9a3fd2f02e9e8f
  F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
  F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
  F src/ctime.c 4262c227bc91cecc61ae37ed3a40f08069cfa267
@@@ -289,7 -289,7 +289,7 @@@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb
  F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
  F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
  F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
- F src/where.c 58522e12fcb559ac138d1cf51348b6861345968e
 -F src/where.c 5c4cbc1e5205d8d534c483fa4495c81513b45dea
++F src/where.c 97f5d9c3a9dfa802d91f7723cd1d782a3ce78e7a
  F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
  F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
  F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@@ -359,14 -359,14 +359,14 @@@ F test/capi3.test 56ab450125ead38846cba
  F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
  F test/capi3c.test 93d24621c9ff84da9da060f30431e0453db1cdb0
  F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1
 -F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
 +F test/capi3e.test ad90088b18b0367125ff2d4b5400153fd2f99aab
  F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
  F test/check.test 2eb93611139a7dfaed3be80067c7dc5ceb5fb287
 -F test/close.test e37610d60e9c9b9979a981f3f50071d7dff28616
 +F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
  F test/closure01.test dbb28f1ea9eeaf0a53ec5bc0fed352e479def8c7
  F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
- F test/collate1.test fd02c4d8afc71879c4bb952586389961a21fb0ce
+ F test/collate1.test b709989e6e6ff6e1d2bd64231c2c1d8146846c9e
 -F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
 +F test/collate2.test 285cef1b58ce2b3cf074a386f763ce753c81c97f
  F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f
  F test/collate4.test 031f7265c13308b724ba3c49f41cc04612bd92b1
  F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6
@@@ -1093,9 -1092,8 +1093,9 @@@ F tool/tostr.awk e75472c2f98dd76e06b8c9
  F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
  F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
  F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 +F tool/wherecosttest.c 4d0393bdbe7230adb712e925863744dd2b7ffc5b
  F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
- P 25e2cde105a19293bdb9c001b48624e5d7f8c4e5
- R 74299348f4ebeefec70a5406f9e251d7
 -P 7e3820e5b989426c64af46f6bf862b91366ae954
 -R 5f94a46cd24d5603b852ca86ea7eaf5a
 -U dan
 -Z 30f6897d1a48f4a9b1a79c1749e033ce
++P addd7f466d6ff55f82d907286650c26b06e9397b 24fc9d4438a5615dd20af5419456166df83a72ea
++R 400236daf5743c1455f090bd73116cba
 +U drh
- Z ad22135d0c0bd81f6331e3b3327b23e1
++Z eafccaa2bb28a08ba2c2409a2846f8df
diff --cc manifest.uuid
index 16f0323d65916534c5bb4c081541536703ba7b95,87e2685a1649eb3930945e3d9c82e2889abcdeb5..9a98bfb402ade9e967418d00cb7cb120afac54c1
@@@ -1,1 -1,1 +1,1 @@@
- addd7f466d6ff55f82d907286650c26b06e9397b
 -24fc9d4438a5615dd20af5419456166df83a72ea
++f2e15b1974e55373b5819e3b2326653f890f409f
diff --cc src/build.c
Simple merge
diff --cc src/where.c
index 9886d4e214faecf3d9f546c94c04debe86a8e5a5,e614f4a6d864e70ec4328d0bdb254e3ac9f0d287..abf4ebf56e4f3a9149f78ccabd385eca6c6a9c49
@@@ -39,114 -38,7 +39,114 @@@ typedef struct WhereClause WhereClause
  typedef struct WhereMaskSet WhereMaskSet;
  typedef struct WhereOrInfo WhereOrInfo;
  typedef struct WhereAndInfo WhereAndInfo;
 -typedef struct WhereCost WhereCost;
 +typedef struct WhereLevel WhereLevel;
 +typedef struct WhereLoop WhereLoop;
 +typedef struct WherePath WherePath;
 +typedef struct WhereTerm WhereTerm;
 +typedef struct WhereLoopBuilder WhereLoopBuilder;
 +typedef struct WhereScan WhereScan;
 +
 +/*
 +** Cost X is tracked as 10*log2(X) stored in a 16-bit integer.  The
 +** maximum cost is 64*(2**63) which becomes 6900.  So all costs can be
 +** be stored in a 16-bit unsigned integer without risk of overflow.
 +*/
 +typedef unsigned short int WhereCost;
 +
 +/*
 +** For each nested loop in a WHERE clause implementation, the WhereInfo
 +** structure contains a single instance of this structure.  This structure
 +** is intended to be private to the where.c module and should not be
 +** access or modified by other modules.
 +**
 +** The pIdxInfo field is used to help pick the best index on a
 +** virtual table.  The pIdxInfo pointer contains indexing
 +** information for the i-th table in the FROM clause before reordering.
 +** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
 +** All other information in the i-th WhereLevel object for the i-th table
 +** after FROM clause ordering.
 +*/
 +struct WhereLevel {
 +  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
 +  int iTabCur;          /* The VDBE cursor used to access the table */
 +  int iIdxCur;          /* The VDBE cursor used to access pIdx */
 +  int addrBrk;          /* Jump here to break out of the loop */
 +  int addrNxt;          /* Jump here to start the next IN combination */
 +  int addrCont;         /* Jump here to continue with the next loop cycle */
 +  int addrFirst;        /* First instruction of interior of the loop */
 +  u8 iFrom;             /* Which entry in the FROM clause */
 +  u8 op, p5;            /* Opcode and P5 of the opcode that ends the loop */
 +  int p1, p2;           /* Operands of the opcode used to ends the loop */
-   union {               /* Information that depends on plan.wsFlags */
++  union {               /* Information that depends on pWLoop->wsFlags */
 +    struct {
 +      int nIn;              /* Number of entries in aInLoop[] */
 +      struct InLoop {
 +        int iCur;              /* The VDBE cursor used by this IN operator */
 +        int addrInTop;         /* Top of the IN loop */
 +        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
 +      } *aInLoop;           /* Information about each nested IN operator */
-     } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
++    } in;                 /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
 +    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
 +  } u;
 +  struct WhereLoop *pWLoop;  /* The selected WhereLoop object */
 +};
 +
 +/*
 +** Each instance of this object represents a way of evaluating one
 +** term of a join.  The WhereClause object holds a table of these
 +** objects using (maskSelf,prereq,) as the primary key.  Note that the
 +** same join term might have multiple associated WhereLoop objects.
 +*/
 +struct WhereLoop {
 +  Bitmask prereq;       /* Bitmask of other loops that must run first */
 +  Bitmask maskSelf;     /* Bitmask identifying table iTab */
 +#ifdef SQLITE_DEBUG
 +  char cId;             /* Symbolic ID of this loop for debugging use */
 +#endif
 +  u8 iTab;              /* Position in FROM clause of table for this loop */
 +  u8 iSortIdx;          /* Sorting index number.  0==None */
 +  WhereCost rSetup;     /* One-time setup cost (ex: create transient index) */
 +  WhereCost rRun;       /* Cost of running each loop */
 +  WhereCost nOut;       /* Estimated number of output rows */
 +  union {
 +    struct {               /* Information for internal btree tables */
 +      int nEq;               /* Number of equality constraints */
 +      Index *pIndex;         /* Index used, or NULL */
 +    } btree;
 +    struct {               /* Information for virtual tables */
 +      int idxNum;            /* Index number */
 +      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
 +      u8 isOrdered;          /* True if satisfies ORDER BY */
 +      u16 omitMask;          /* Terms that may be omitted */
 +      char *idxStr;          /* Index identifier string */
 +    } vtab;
 +  } u;
 +  u32 wsFlags;          /* WHERE_* flags describing the plan */
 +  u16 nLTerm;           /* Number of entries in aLTerm[] */
 +  /**** whereLoopXfer() copies fields above ***********************/
 +# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
 +  u16 nLSlot;           /* Number of slots allocated for aLTerm[] */
 +  WhereTerm **aLTerm;   /* WhereTerms used */
 +  WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
 +  WhereTerm *aLTermSpace[4];  /* Initial aLTerm[] space */
 +};
 +
 +/* Forward declaration of methods */
 +static int whereLoopResize(sqlite3*, WhereLoop*, int);
 +
 +/*
 +** Each instance of this object holds a sequence of WhereLoop objects
 +** that implement some or all of the entire query plan.  
 +*/
 +struct WherePath {
 +  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
 +  Bitmask revLoop;      /* aLoop[]s that should be reversed for ORDER BY */
 +  WhereCost nRow;       /* Estimated number of rows generated by this path */
 +  WhereCost rCost;      /* Total cost of this path */
 +  u8 isOrdered;         /* True if this path satisfies ORDER BY */
 +  u8 isOrderedValid;    /* True if the isOrdered field is valid */
 +  WhereLoop **aLoop;    /* Array of WhereLoop objects implementing this path */
 +};
  
  /*
  ** The query generator uses an array of instances of this structure to
@@@ -2734,88 -2897,947 +2734,86 @@@ static void disableTerm(WhereLevel *pLe
  }
  
  /*
 -** This routine decides if pIdx can be used to satisfy the ORDER BY
 -** clause, either in whole or in part.  The return value is the 
 -** cumulative number of terms in the ORDER BY clause that are satisfied
 -** by the index pIdx and other indices in outer loops.
 +** Code an OP_Affinity opcode to apply the column affinity string zAff
 +** to the n registers starting at base. 
  **
 -** The table being queried has a cursor number of "base".  pIdx is the
 -** index that is postulated for use to access the table.
 +** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
 +** beginning and end of zAff are ignored.  If all entries in zAff are
 +** SQLITE_AFF_NONE, then no code gets generated.
  **
 -** The *pbRev value is set to 0 order 1 depending on whether or not
 -** pIdx should be run in the forward order or in reverse order.
 +** This routine makes its own copy of zAff so that the caller is free
 +** to modify zAff after this routine returns.
  */
 -static int isSortingIndex(
 -  WhereBestIdx *p,    /* Best index search context */
 -  Index *pIdx,        /* The index we are testing */
 -  int base,           /* Cursor number for the table to be sorted */
 -  int *pbRev,         /* Set to 1 for reverse-order scan of pIdx */
 -  int *pbObUnique     /* ORDER BY column values will different in every row */
 -){
 -  int i;                        /* Number of pIdx terms used */
 -  int j;                        /* Number of ORDER BY terms satisfied */
 -  int sortOrder = 2;            /* 0: forward.  1: backward.  2: unknown */
 -  int nTerm;                    /* Number of ORDER BY terms */
 -  struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
 -  Table *pTab = pIdx->pTable;   /* Table that owns index pIdx */
 -  ExprList *pOrderBy;           /* The ORDER BY clause */
 -  Parse *pParse = p->pParse;    /* Parser context */
 -  sqlite3 *db = pParse->db;     /* Database connection */
 -  int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
 -  int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
 -  int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
 -  int outerObUnique;            /* Outer loops generate different values in
 -                                ** every row for the ORDER BY columns */
 -
 -  if( p->i==0 ){
 -    nPriorSat = 0;
 -    outerObUnique = 1;
 -  }else{
 -    u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
 -    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
 -    if( (wsFlags & WHERE_ORDERED)==0 ){
 -      /* This loop cannot be ordered unless the next outer loop is
 -      ** also ordered */
 -      return nPriorSat;
 -    }
 -    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
 -      /* Only look at the outer-most loop if the OrderByIdxJoin
 -      ** optimization is disabled */
 -      return nPriorSat;
 -    }
 -    testcase( wsFlags & WHERE_OB_UNIQUE );
 -    testcase( wsFlags & WHERE_ALL_UNIQUE );
 -    outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
 -  }
 -  pOrderBy = p->pOrderBy;
 -  assert( pOrderBy!=0 );
 -  if( pIdx->bUnordered ){
 -    /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
 -    ** be used for sorting */
 -    return nPriorSat;
 -  }
 -  nTerm = pOrderBy->nExpr;
 -  uniqueNotNull = pIdx->onError!=OE_None;
 -  assert( nTerm>0 );
 -
 -  /* Argument pIdx must either point to a 'real' named index structure, 
 -  ** or an index structure allocated on the stack by bestBtreeIndex() to
 -  ** represent the rowid index that is part of every table.  */
 -  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
 -
 -  /* Match terms of the ORDER BY clause against columns of
 -  ** the index.
 -  **
 -  ** Note that indices have pIdx->nColumn regular columns plus
 -  ** one additional column containing the rowid.  The rowid column
 -  ** of the index is also allowed to match against the ORDER BY
 -  ** clause.
 -  */
 -  j = nPriorSat;
 -  for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
 -    Expr *pOBExpr;          /* The expression of the ORDER BY pOBItem */
 -    CollSeq *pColl;         /* The collating sequence of pOBExpr */
 -    int termSortOrder;      /* Sort order for this term */
 -    int iColumn;            /* The i-th column of the index.  -1 for rowid */
 -    int iSortOrder;         /* 1 for DESC, 0 for ASC on the i-th index term */
 -    int isEq;               /* Subject to an == or IS NULL constraint */
 -    int isMatch;            /* ORDER BY term matches the index term */
 -    const char *zColl;      /* Name of collating sequence for i-th index term */
 -    WhereTerm *pConstraint; /* A constraint in the WHERE clause */
 -
 -    /* If the next term of the ORDER BY clause refers to anything other than
 -    ** a column in the "base" table, then this index will not be of any
 -    ** further use in handling the ORDER BY. */
 -    pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
 -    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
 -      break;
 -    }
 -
 -    /* Find column number and collating sequence for the next entry
 -    ** in the index */
 -    if( pIdx->zName && i<pIdx->nColumn ){
 -      iColumn = pIdx->aiColumn[i];
 -      if( iColumn==pIdx->pTable->iPKey ){
 -        iColumn = -1;
 -      }
 -      iSortOrder = pIdx->aSortOrder[i];
 -      zColl = pIdx->azColl[i];
 -      assert( zColl!=0 );
 -    }else{
 -      iColumn = -1;
 -      iSortOrder = 0;
 -      zColl = 0;
 -    }
 -
 -    /* Check to see if the column number and collating sequence of the
 -    ** index match the column number and collating sequence of the ORDER BY
 -    ** clause entry.  Set isMatch to 1 if they both match. */
 -    if( pOBExpr->iColumn==iColumn ){
 -      if( zColl ){
 -        pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
 -        if( !pColl ) pColl = db->pDfltColl;
 -        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
 -      }else{
 -        isMatch = 1;
 -      }
 -    }else{
 -      isMatch = 0;
 -    }
 -
 -    /* termSortOrder is 0 or 1 for whether or not the access loop should
 -    ** run forward or backwards (respectively) in order to satisfy this 
 -    ** term of the ORDER BY clause. */
 -    assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
 -    assert( iSortOrder==0 || iSortOrder==1 );
 -    termSortOrder = iSortOrder ^ pOBItem->sortOrder;
 -
 -    /* If X is the column in the index and ORDER BY clause, check to see
 -    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
 -    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
 -                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
 -    if( pConstraint==0 ){
 -      isEq = 0;
 -    }else if( (pConstraint->eOperator & WO_IN)!=0 ){
 -      isEq = 0;
 -    }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
 -      uniqueNotNull = 0;
 -      isEq = 1;  /* "X IS NULL" means X has only a single value */
 -    }else if( pConstraint->prereqRight==0 ){
 -      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
 -    }else{
 -      Expr *pRight = pConstraint->pExpr->pRight;
 -      if( pRight->op==TK_COLUMN ){
 -        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
 -                    pRight->iTable, pRight->iColumn));
 -        isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
 -        WHERETRACE((" -> isEq=%d\n", isEq));
 -
 -        /* If the constraint is of the form X=Y where Y is an ordered value
 -        ** in an outer loop, then make sure the sort order of Y matches the
 -        ** sort order required for X. */
 -        if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
 -          testcase( isEq==2 );
 -          testcase( isEq==3 );
 -          break;
 -        }
 -      }else{
 -        isEq = 0;  /* "X=expr" places no ordering constraints on X */
 -      }
 -    }
 -    if( !isMatch ){
 -      if( isEq==0 ){
 -        break;
 -      }else{
 -        continue;
 -      }
 -    }else if( isEq!=1 ){
 -      if( sortOrder==2 ){
 -        sortOrder = termSortOrder;
 -      }else if( termSortOrder!=sortOrder ){
 -        break;
 -      }
 -    }
 -    j++;
 -    pOBItem++;
 -    if( iColumn<0 ){
 -      seenRowid = 1;
 -      break;
 -    }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
 -      testcase( isEq==0 );
 -      testcase( isEq==2 );
 -      testcase( isEq==3 );
 -      uniqueNotNull = 0;
 -    }
 -  }
 -  if( seenRowid ){
 -    uniqueNotNull = 1;
 -  }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
 -    uniqueNotNull = 0;
 +static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
 +  Vdbe *v = pParse->pVdbe;
 +  if( zAff==0 ){
 +    assert( pParse->db->mallocFailed );
 +    return;
    }
 +  assert( v!=0 );
  
 -  /* If we have not found at least one ORDER BY term that matches the
 -  ** index, then show no progress. */
 -  if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
 -
 -  /* Either the outer queries must generate rows where there are no two
 -  ** rows with the same values in all ORDER BY columns, or else this
 -  ** loop must generate just a single row of output.  Example:  Suppose
 -  ** the outer loops generate A=1 and A=1, and this loop generates B=3
 -  ** and B=4.  Then without the following test, ORDER BY A,B would 
 -  ** generate the wrong order output: 1,3 1,4 1,3 1,4
 +  /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
 +  ** and end of the affinity string.
    */
 -  if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
 -  *pbObUnique = uniqueNotNull;
 -
 -  /* Return the necessary scan order back to the caller */
 -  *pbRev = sortOrder & 1;
 +  while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
 +    n--;
 +    base++;
 +    zAff++;
 +  }
 +  while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
 +    n--;
 +  }
  
 -  /* If there was an "ORDER BY rowid" term that matched, or it is only
 -  ** possible for a single row from this table to match, then skip over
 -  ** any additional ORDER BY terms dealing with this table.
 -  */
 -  if( uniqueNotNull ){
 -    /* Advance j over additional ORDER BY terms associated with base */
 -    WhereMaskSet *pMS = p->pWC->pMaskSet;
 -    Bitmask m = ~getMask(pMS, base);
 -    while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
 -      j++;
 -    }
 +  /* Code the OP_Affinity opcode if there is anything left to do. */
 +  if( n>0 ){
 +    sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
 +    sqlite3VdbeChangeP4(v, -1, zAff, n);
 +    sqlite3ExprCacheAffinityChange(pParse, base, n);
    }
 -  return j;
  }
  
 +
  /*
 -** Find the best query plan for accessing a particular table.  Write the
 -** best query plan and its cost into the p->cost.
 -**
 -** The lowest cost plan wins.  The cost is an estimate of the amount of
 -** CPU and disk I/O needed to process the requested result.
 -** Factors that influence cost include:
 -**
 -**    *  The estimated number of rows that will be retrieved.  (The
 -**       fewer the better.)
 -**
 -**    *  Whether or not sorting must occur.
 -**
 -**    *  Whether or not there must be separate lookups in the
 -**       index and in the main table.
 +** Generate code for a single equality term of the WHERE clause.  An equality
 +** term can be either X=expr or X IN (...).   pTerm is the term to be 
 +** coded.
  **
 -** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
 -** the SQL statement, then this function only considers plans using the 
 -** named index. If no such plan is found, then the returned cost is
 -** SQLITE_BIG_DBL. If a plan is found that uses the named index, 
 -** then the cost is calculated in the usual way.
 +** The current value for the constraint is left in register iReg.
  **
 -** If a NOT INDEXED clause was attached to the table 
 -** in the SELECT statement, then no indexes are considered. However, the 
 -** selected plan may still take advantage of the built-in rowid primary key
 -** index.
 +** For a constraint of the form X=expr, the expression is evaluated and its
 +** result is left on the stack.  For constraints of the form X IN (...)
 +** this routine sets up a loop that will iterate over all values of X.
  */
 -static void bestBtreeIndex(WhereBestIdx *p){
 -  Parse *pParse = p->pParse;  /* The parsing context */
 -  WhereClause *pWC = p->pWC;  /* The WHERE clause */
 -  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
 -  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
 -  Index *pProbe;              /* An index we are evaluating */
 -  Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
 -  int eqTermMask;             /* Current mask of valid equality operators */
 -  int idxEqTermMask;          /* Index mask of valid equality operators */
 -  Index sPk;                  /* A fake index object for the primary key */
 -  tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
 -  int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
 -  int wsFlagMask;             /* Allowed flags in p->cost.plan.wsFlag */
 -  int nPriorSat;              /* ORDER BY terms satisfied by outer loops */
 -  int nOrderBy;               /* Number of ORDER BY terms */
 -  char bSortInit;             /* Initializer for bSort in inner loop */
 -  char bDistInit;             /* Initializer for bDist in inner loop */
 -
 -
 -  /* Initialize the cost to a worst-case value */
 -  memset(&p->cost, 0, sizeof(p->cost));
 -  p->cost.rCost = SQLITE_BIG_DBL;
 +static int codeEqualityTerm(
 +  Parse *pParse,      /* The parsing context */
 +  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
 +  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
 +  int iEq,            /* Index of the equality term within this level */
 +  int bRev,           /* True for reverse-order IN operations */
 +  int iTarget         /* Attempt to leave results in this register */
 +){
 +  Expr *pX = pTerm->pExpr;
 +  Vdbe *v = pParse->pVdbe;
 +  int iReg;                  /* Register holding results */
  
 -  /* If the pSrc table is the right table of a LEFT JOIN then we may not
 -  ** use an index to satisfy IS NULL constraints on that table.  This is
 -  ** because columns might end up being NULL if the table does not match -
 -  ** a circumstance which the index cannot help us discover.  Ticket #2177.
 -  */
 -  if( pSrc->jointype & JT_LEFT ){
 -    idxEqTermMask = WO_EQ|WO_IN;
 +  assert( iTarget>0 );
 +  if( pX->op==TK_EQ ){
 +    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
 +  }else if( pX->op==TK_ISNULL ){
 +    iReg = iTarget;
 +    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
 +#ifndef SQLITE_OMIT_SUBQUERY
    }else{
 -    idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL;
 -  }
 +    int eType;
 +    int iTab;
 +    struct InLoop *pIn;
 +    WhereLoop *pLoop = pLevel->pWLoop;
  
 -  if( pSrc->pIndex ){
 -    /* An INDEXED BY clause specifies a particular index to use */
 -    pIdx = pProbe = pSrc->pIndex;
 -    wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
 -    eqTermMask = idxEqTermMask;
 -  }else{
 -    /* There is no INDEXED BY clause.  Create a fake Index object in local
 -    ** variable sPk to represent the rowid primary key index.  Make this
 -    ** fake index the first in a chain of Index objects with all of the real
 -    ** indices to follow */
 -    Index *pFirst;                  /* First of real indices on the table */
 -    memset(&sPk, 0, sizeof(Index));
 -    sPk.nColumn = 1;
 -    sPk.aiColumn = &aiColumnPk;
 -    sPk.aiRowEst = aiRowEstPk;
 -    sPk.onError = OE_Replace;
 -    sPk.pTable = pSrc->pTab;
 -    aiRowEstPk[0] = pSrc->pTab->nRowEst;
 -    aiRowEstPk[1] = 1;
 -    pFirst = pSrc->pTab->pIndex;
 -    if( pSrc->notIndexed==0 ){
 -      /* The real indices of the table are only considered if the
 -      ** NOT INDEXED qualifier is omitted from the FROM clause */
 -      sPk.pNext = pFirst;
 -    }
 -    pProbe = &sPk;
 -    wsFlagMask = ~(
 -        WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
 -    );
 -    eqTermMask = WO_EQ|WO_IN;
 -    pIdx = 0;
 -  }
 -
 -  nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
 -  if( p->i ){
 -    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
 -    bSortInit = nPriorSat<nOrderBy;
 -    bDistInit = 0;
 -  }else{
 -    nPriorSat = 0;
 -    bSortInit = nOrderBy>0;
 -    bDistInit = p->pDistinct!=0;
 -  }
 -
 -  /* Loop over all indices looking for the best one to use
 -  */
 -  for(; pProbe; pIdx=pProbe=pProbe->pNext){
 -    const tRowcnt * const aiRowEst = pProbe->aiRowEst;
 -    WhereCost pc;               /* Cost of using pProbe */
 -    double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */
 -
 -    /* The following variables are populated based on the properties of
 -    ** index being evaluated. They are then used to determine the expected
 -    ** cost and number of rows returned.
 -    **
 -    **  pc.plan.nEq: 
 -    **    Number of equality terms that can be implemented using the index.
 -    **    In other words, the number of initial fields in the index that
 -    **    are used in == or IN or NOT NULL constraints of the WHERE clause.
 -    **
 -    **  nInMul:  
 -    **    The "in-multiplier". This is an estimate of how many seek operations 
 -    **    SQLite must perform on the index in question. For example, if the 
 -    **    WHERE clause is:
 -    **
 -    **      WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
 -    **
 -    **    SQLite must perform 9 lookups on an index on (a, b), so nInMul is 
 -    **    set to 9. Given the same schema and either of the following WHERE 
 -    **    clauses:
 -    **
 -    **      WHERE a =  1
 -    **      WHERE a >= 2
 -    **
 -    **    nInMul is set to 1.
 -    **
 -    **    If there exists a WHERE term of the form "x IN (SELECT ...)", then 
 -    **    the sub-select is assumed to return 25 rows for the purposes of 
 -    **    determining nInMul.
 -    **
 -    **  bInEst:  
 -    **    Set to true if there was at least one "x IN (SELECT ...)" term used 
 -    **    in determining the value of nInMul.  Note that the RHS of the
 -    **    IN operator must be a SELECT, not a value list, for this variable
 -    **    to be true.
 -    **
 -    **  rangeDiv:
 -    **    An estimate of a divisor by which to reduce the search space due
 -    **    to inequality constraints.  In the absence of sqlite_stat3 ANALYZE
 -    **    data, a single inequality reduces the search space to 1/4rd its
 -    **    original size (rangeDiv==4).  Two inequalities reduce the search
 -    **    space to 1/16th of its original size (rangeDiv==16).
 -    **
 -    **  bSort:   
 -    **    Boolean. True if there is an ORDER BY clause that will require an 
 -    **    external sort (i.e. scanning the index being evaluated will not 
 -    **    correctly order records).
 -    **
 -    **  bDist:
 -    **    Boolean. True if there is a DISTINCT clause that will require an 
 -    **    external btree.
 -    **
 -    **  bLookup: 
 -    **    Boolean. True if a table lookup is required for each index entry
 -    **    visited.  In other words, true if this is not a covering index.
 -    **    This is always false for the rowid primary key index of a table.
 -    **    For other indexes, it is true unless all the columns of the table
 -    **    used by the SELECT statement are present in the index (such an
 -    **    index is sometimes described as a covering index).
 -    **    For example, given the index on (a, b), the second of the following 
 -    **    two queries requires table b-tree lookups in order to find the value
 -    **    of column c, but the first does not because columns a and b are
 -    **    both available in the index.
 -    **
 -    **             SELECT a, b    FROM tbl WHERE a = 1;
 -    **             SELECT a, b, c FROM tbl WHERE a = 1;
 -    */
 -    int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
 -    int nInMul = 1;               /* Number of distinct equalities to lookup */
 -    double rangeDiv = (double)1;  /* Estimated reduction in search space */
 -    int nBound = 0;               /* Number of range constraints seen */
 -    char bSort = bSortInit;       /* True if external sort required */
 -    char bDist = bDistInit;       /* True if index cannot help with DISTINCT */
 -    char bLookup = 0;             /* True if not a covering index */
 -    WhereTerm *pTerm;             /* A single term of the WHERE clause */
 -#ifdef SQLITE_ENABLE_STAT3
 -    WhereTerm *pFirstTerm = 0;    /* First term matching the index */
 -#endif
 -
 -    WHERETRACE((
 -      "   %s(%s):\n",
 -      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
 -    ));
 -    memset(&pc, 0, sizeof(pc));
 -    pc.plan.nOBSat = nPriorSat;
 -
 -    /* Determine the values of pc.plan.nEq and nInMul */
 -    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
 -      int j = pProbe->aiColumn[pc.plan.nEq];
 -      pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
 -      if( pTerm==0 ) break;
 -      pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
 -      testcase( pTerm->pWC!=pWC );
 -      if( pTerm->eOperator & WO_IN ){
 -        Expr *pExpr = pTerm->pExpr;
 -        pc.plan.wsFlags |= WHERE_COLUMN_IN;
 -        if( ExprHasProperty(pExpr, EP_xIsSelect) ){
 -          /* "x IN (SELECT ...)":  Assume the SELECT returns 25 rows */
 -          nInMul *= 25;
 -          bInEst = 1;
 -        }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
 -          /* "x IN (value, value, ...)" */
 -          nInMul *= pExpr->x.pList->nExpr;
 -        }
 -      }else if( pTerm->eOperator & WO_ISNULL ){
 -        pc.plan.wsFlags |= WHERE_COLUMN_NULL;
 -      }
 -#ifdef SQLITE_ENABLE_STAT3
 -      if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
 -#endif
 -      pc.used |= pTerm->prereqRight;
 -    }
 - 
 -    /* If the index being considered is UNIQUE, and there is an equality 
 -    ** constraint for all columns in the index, then this search will find
 -    ** at most a single row. In this case set the WHERE_UNIQUE flag to 
 -    ** indicate this to the caller.
 -    **
 -    ** Otherwise, if the search may find more than one row, test to see if
 -    ** there is a range constraint on indexed column (pc.plan.nEq+1) that
 -    ** can be optimized using the index. 
 -    */
 -    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
 -      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
 -      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
 -      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
 -        pc.plan.wsFlags |= WHERE_UNIQUE;
 -        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
 -          pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
 -        }
 -      }
 -    }else if( pProbe->bUnordered==0 ){
 -      int j;
 -      j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
 -      if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
 -        WhereTerm *pTop, *pBtm;
 -        pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
 -        pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
 -        whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
 -        if( pTop ){
 -          nBound = 1;
 -          pc.plan.wsFlags |= WHERE_TOP_LIMIT;
 -          pc.used |= pTop->prereqRight;
 -          testcase( pTop->pWC!=pWC );
 -        }
 -        if( pBtm ){
 -          nBound++;
 -          pc.plan.wsFlags |= WHERE_BTM_LIMIT;
 -          pc.used |= pBtm->prereqRight;
 -          testcase( pBtm->pWC!=pWC );
 -        }
 -        pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
 -      }
 -    }
 -
 -    /* If there is an ORDER BY clause and the index being considered will
 -    ** naturally scan rows in the required order, set the appropriate flags
 -    ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
 -    ** the index will scan rows in a different order, set the bSort
 -    ** variable.  */
 -    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
 -      int bRev = 2;
 -      int bObUnique = 0;
 -      WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
 -      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
 -      WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
 -                  bRev, bObUnique, pc.plan.nOBSat));
 -      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
 -        pc.plan.wsFlags |= WHERE_ORDERED;
 -        if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
 -      }
 -      if( nOrderBy==pc.plan.nOBSat ){
 -        bSort = 0;
 -        pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
 -      }
 -      if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
 -    }
 -
 -    /* If there is a DISTINCT qualifier and this index will scan rows in
 -    ** order of the DISTINCT expressions, clear bDist and set the appropriate
 -    ** flags in pc.plan.wsFlags. */
 -    if( bDist
 -     && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
 -     && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
 -    ){
 -      bDist = 0;
 -      pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
 -    }
 -
 -    /* If currently calculating the cost of using an index (not the IPK
 -    ** index), determine if all required column data may be obtained without 
 -    ** using the main table (i.e. if the index is a covering
 -    ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
 -    ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true.  */
 -    if( pIdx ){
 -      Bitmask m = pSrc->colUsed;
 -      int j;
 -      for(j=0; j<pIdx->nColumn; j++){
 -        int x = pIdx->aiColumn[j];
 -        if( x<BMS-1 ){
 -          m &= ~(((Bitmask)1)<<x);
 -        }
 -      }
 -      if( m==0 ){
 -        pc.plan.wsFlags |= WHERE_IDX_ONLY;
 -      }else{
 -        bLookup = 1;
 -      }
 -    }
 -
 -    /*
 -    ** Estimate the number of rows of output.  For an "x IN (SELECT...)"
 -    ** constraint, do not let the estimate exceed half the rows in the table.
 -    */
 -    pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
 -    if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
 -      pc.plan.nRow = aiRowEst[0]/2;
 -      nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
 -    }
 -
 -#ifdef SQLITE_ENABLE_STAT3
 -    /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
 -    ** and we do not think that values of x are unique and if histogram
 -    ** data is available for column x, then it might be possible
 -    ** to get a better estimate on the number of rows based on
 -    ** VALUE and how common that value is according to the histogram.
 -    */
 -    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
 -     && pFirstTerm!=0 && aiRowEst[1]>1 ){
 -      assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
 -      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
 -        testcase( pFirstTerm->eOperator & WO_EQ );
 -        testcase( pFirstTerm->eOperator & WO_EQUIV );
 -        testcase( pFirstTerm->eOperator & WO_ISNULL );
 -        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
 -                          &pc.plan.nRow);
 -      }else if( bInEst==0 ){
 -        assert( pFirstTerm->eOperator & WO_IN );
 -        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
 -                       &pc.plan.nRow);
 -      }
 -    }
 -#endif /* SQLITE_ENABLE_STAT3 */
 -
 -    /* Adjust the number of output rows and downward to reflect rows
 -    ** that are excluded by range constraints.
 -    */
 -    pc.plan.nRow = pc.plan.nRow/rangeDiv;
 -    if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
 -
 -    /* Experiments run on real SQLite databases show that the time needed
 -    ** to do a binary search to locate a row in a table or index is roughly
 -    ** log10(N) times the time to move from one row to the next row within
 -    ** a table or index.  The actual times can vary, with the size of
 -    ** records being an important factor.  Both moves and searches are
 -    ** slower with larger records, presumably because fewer records fit
 -    ** on one page and hence more pages have to be fetched.
 -    **
 -    ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
 -    ** not give us data on the relative sizes of table and index records.
 -    ** So this computation assumes table records are about twice as big
 -    ** as index records
 -    */
 -    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
 -                                                              ==WHERE_IDX_ONLY
 -     && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
 -     && sqlite3GlobalConfig.bUseCis
 -     && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
 -    ){
 -      /* This index is not useful for indexing, but it is a covering index.
 -      ** A full-scan of the index might be a little faster than a full-scan
 -      ** of the table, so give this case a cost slightly less than a table
 -      ** scan. */
 -      pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
 -      pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
 -    }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
 -      /* The cost of a full table scan is a number of move operations equal
 -      ** to the number of rows in the table.
 -      **
 -      ** We add an additional 4x penalty to full table scans.  This causes
 -      ** the cost function to err on the side of choosing an index over
 -      ** choosing a full scan.  This 4x full-scan penalty is an arguable
 -      ** decision and one which we expect to revisit in the future.  But
 -      ** it seems to be working well enough at the moment.
 -      */
 -      pc.rCost = aiRowEst[0]*4;
 -      pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
 -      if( pIdx ){
 -        pc.plan.wsFlags &= ~WHERE_ORDERED;
 -        pc.plan.nOBSat = nPriorSat;
 -      }
 -    }else{
 -      log10N = estLog(aiRowEst[0]);
 -      pc.rCost = pc.plan.nRow;
 -      if( pIdx ){
 -        if( bLookup ){
 -          /* For an index lookup followed by a table lookup:
 -          **    nInMul index searches to find the start of each index range
 -          **  + nRow steps through the index
 -          **  + nRow table searches to lookup the table entry using the rowid
 -          */
 -          pc.rCost += (nInMul + pc.plan.nRow)*log10N;
 -        }else{
 -          /* For a covering index:
 -          **     nInMul index searches to find the initial entry 
 -          **   + nRow steps through the index
 -          */
 -          pc.rCost += nInMul*log10N;
 -        }
 -      }else{
 -        /* For a rowid primary key lookup:
 -        **    nInMult table searches to find the initial entry for each range
 -        **  + nRow steps through the table
 -        */
 -        pc.rCost += nInMul*log10N;
 -      }
 -    }
 -
 -    /* Add in the estimated cost of sorting the result.  Actual experimental
 -    ** measurements of sorting performance in SQLite show that sorting time
 -    ** adds C*N*log10(N) to the cost, where N is the number of rows to be 
 -    ** sorted and C is a factor between 1.95 and 4.3.  We will split the
 -    ** difference and select C of 3.0.
 -    */
 -    if( bSort ){
 -      double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
 -      m *= (double)(pc.plan.nOBSat ? 2 : 3);
 -      pc.rCost += pc.plan.nRow*m;
 -    }
 -    if( bDist ){
 -      pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
 -    }
 -
 -    /**** Cost of using this index has now been computed ****/
 -
 -    /* If there are additional constraints on this table that cannot
 -    ** be used with the current index, but which might lower the number
 -    ** of output rows, adjust the nRow value accordingly.  This only 
 -    ** matters if the current index is the least costly, so do not bother
 -    ** with this step if we already know this index will not be chosen.
 -    ** Also, never reduce the output row count below 2 using this step.
 -    **
 -    ** It is critical that the notValid mask be used here instead of
 -    ** the notReady mask.  When computing an "optimal" index, the notReady
 -    ** mask will only have one bit set - the bit for the current table.
 -    ** The notValid mask, on the other hand, always has all bits set for
 -    ** tables that are not in outer loops.  If notReady is used here instead
 -    ** of notValid, then a optimal index that depends on inner joins loops
 -    ** might be selected even when there exists an optimal index that has
 -    ** no such dependency.
 -    */
 -    if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
 -      int k;                       /* Loop counter */
 -      int nSkipEq = pc.plan.nEq;   /* Number of == constraints to skip */
 -      int nSkipRange = nBound;     /* Number of < constraints to skip */
 -      Bitmask thisTab;             /* Bitmap for pSrc */
 -
 -      thisTab = getMask(pWC->pMaskSet, iCur);
 -      for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
 -        if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
 -        if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
 -        if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
 -          if( nSkipEq ){
 -            /* Ignore the first pc.plan.nEq equality matches since the index
 -            ** has already accounted for these */
 -            nSkipEq--;
 -          }else{
 -            /* Assume each additional equality match reduces the result
 -            ** set size by a factor of 10 */
 -            pc.plan.nRow /= 10;
 -          }
 -        }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
 -          if( nSkipRange ){
 -            /* Ignore the first nSkipRange range constraints since the index
 -            ** has already accounted for these */
 -            nSkipRange--;
 -          }else{
 -            /* Assume each additional range constraint reduces the result
 -            ** set size by a factor of 3.  Indexed range constraints reduce
 -            ** the search space by a larger factor: 4.  We make indexed range
 -            ** more selective intentionally because of the subjective 
 -            ** observation that indexed range constraints really are more
 -            ** selective in practice, on average. */
 -            pc.plan.nRow /= 3;
 -          }
 -        }else if( (pTerm->eOperator & WO_NOOP)==0 ){
 -          /* Any other expression lowers the output row count by half */
 -          pc.plan.nRow /= 2;
 -        }
 -      }
 -      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
 -    }
 -
 -
 -    WHERETRACE((
 -      "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
 -      "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
 -      "      used=0x%llx nOBSat=%d\n",
 -      pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
 -      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
 -      pc.plan.nOBSat
 -    ));
 -
 -    /* If this index is the best we have seen so far, then record this
 -    ** index and its cost in the p->cost structure.
 -    */
 -    if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
 -      p->cost = pc;
 -      p->cost.plan.wsFlags &= wsFlagMask;
 -      p->cost.plan.u.pIdx = pIdx;
 -    }
 -
 -    /* If there was an INDEXED BY clause, then only that one index is
 -    ** considered. */
 -    if( pSrc->pIndex ) break;
 -
 -    /* Reset masks for the next index in the loop */
 -    wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
 -    eqTermMask = idxEqTermMask;
 -  }
 -
 -  /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
 -  ** is set, then reverse the order that the index will be scanned
 -  ** in. This is used for application testing, to help find cases
 -  ** where application behavior depends on the (undefined) order that
 -  ** SQLite outputs rows in in the absence of an ORDER BY clause.  */
 -  if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
 -    p->cost.plan.wsFlags |= WHERE_REVERSE;
 -  }
 -
 -  assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
 -  assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
 -  assert( pSrc->pIndex==0 
 -       || p->cost.plan.u.pIdx==0 
 -       || p->cost.plan.u.pIdx==pSrc->pIndex 
 -  );
 -
 -  WHERETRACE(("   best index is %s cost=%.1f\n",
 -         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
 -         p->cost.rCost));
 -  
 -  bestOrClauseIndex(p);
 -  bestAutomaticIndex(p);
 -  p->cost.plan.wsFlags |= eqTermMask;
 -}
 -
 -/*
 -** Find the query plan for accessing table pSrc->pTab. Write the
 -** best query plan and its cost into the WhereCost object supplied 
 -** as the last parameter. This function may calculate the cost of
 -** both real and virtual table scans.
 -**
 -** This function does not take ORDER BY or DISTINCT into account.  Nor
 -** does it remember the virtual table query plan.  All it does is compute
 -** the cost while determining if an OR optimization is applicable.  The
 -** details will be reconsidered later if the optimization is found to be
 -** applicable.
 -*/
 -static void bestIndex(WhereBestIdx *p){
 -#ifndef SQLITE_OMIT_VIRTUALTABLE
 -  if( IsVirtual(p->pSrc->pTab) ){
 -    sqlite3_index_info *pIdxInfo = 0;
 -    p->ppIdxInfo = &pIdxInfo;
 -    bestVirtualIndex(p);
 -    assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
 -    if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
 -      sqlite3_free(pIdxInfo->idxStr);
 -    }
 -    sqlite3DbFree(p->pParse->db, pIdxInfo);
 -  }else
 -#endif
 -  {
 -    bestBtreeIndex(p);
 -  }
 -}
 -
 -/*
 -** Disable a term in the WHERE clause.  Except, do not disable the term
 -** if it controls a LEFT OUTER JOIN and it did not originate in the ON
 -** or USING clause of that join.
 -**
 -** Consider the term t2.z='ok' in the following queries:
 -**
 -**   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
 -**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
 -**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
 -**
 -** The t2.z='ok' is disabled in the in (2) because it originates
 -** in the ON clause.  The term is disabled in (3) because it is not part
 -** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
 -**
 -** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
 -** completely satisfied by indices.
 -**
 -** Disabling a term causes that term to not be tested in the inner loop
 -** of the join.  Disabling is an optimization.  When terms are satisfied
 -** by indices, we disable them to prevent redundant tests in the inner
 -** loop.  We would get the correct results if nothing were ever disabled,
 -** but joins might run a little slower.  The trick is to disable as much
 -** as we can without disabling too much.  If we disabled in (1), we'd get
 -** the wrong answer.  See ticket #813.
 -*/
 -static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
 -  if( pTerm
 -      && (pTerm->wtFlags & TERM_CODED)==0
 -      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
 -  ){
 -    pTerm->wtFlags |= TERM_CODED;
 -    if( pTerm->iParent>=0 ){
 -      WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
 -      if( (--pOther->nChild)==0 ){
 -        disableTerm(pLevel, pOther);
 -      }
 -    }
 -  }
 -}
 -
 -/*
 -** Code an OP_Affinity opcode to apply the column affinity string zAff
 -** to the n registers starting at base. 
 -**
 -** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
 -** beginning and end of zAff are ignored.  If all entries in zAff are
 -** SQLITE_AFF_NONE, then no code gets generated.
 -**
 -** This routine makes its own copy of zAff so that the caller is free
 -** to modify zAff after this routine returns.
 -*/
 -static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
 -  Vdbe *v = pParse->pVdbe;
 -  if( zAff==0 ){
 -    assert( pParse->db->mallocFailed );
 -    return;
 -  }
 -  assert( v!=0 );
 -
 -  /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
 -  ** and end of the affinity string.
 -  */
 -  while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
 -    n--;
 -    base++;
 -    zAff++;
 -  }
 -  while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
 -    n--;
 -  }
 -
 -  /* Code the OP_Affinity opcode if there is anything left to do. */
 -  if( n>0 ){
 -    sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
 -    sqlite3VdbeChangeP4(v, -1, zAff, n);
 -    sqlite3ExprCacheAffinityChange(pParse, base, n);
 -  }
 -}
 -
 -
 -/*
 -** Generate code for a single equality term of the WHERE clause.  An equality
 -** term can be either X=expr or X IN (...).   pTerm is the term to be 
 -** coded.
 -**
 -** The current value for the constraint is left in register iReg.
 -**
 -** For a constraint of the form X=expr, the expression is evaluated and its
 -** result is left on the stack.  For constraints of the form X IN (...)
 -** this routine sets up a loop that will iterate over all values of X.
 -*/
 -static int codeEqualityTerm(
 -  Parse *pParse,      /* The parsing context */
 -  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
 -  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
 -  int iEq,            /* Index of the equality term within this level */
 -  int iTarget         /* Attempt to leave results in this register */
 -){
 -  Expr *pX = pTerm->pExpr;
 -  Vdbe *v = pParse->pVdbe;
 -  int iReg;                  /* Register holding results */
 -
 -  assert( iTarget>0 );
 -  if( pX->op==TK_EQ ){
 -    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
 -  }else if( pX->op==TK_ISNULL ){
 -    iReg = iTarget;
 -    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
 -#ifndef SQLITE_OMIT_SUBQUERY
 -  }else{
 -    int eType;
 -    int iTab;
 -    struct InLoop *pIn;
 -    u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
 -
 -    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 
 -      && pLevel->plan.u.pIdx->aSortOrder[iEq]
 +    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
 +      && pLoop->u.btree.pIndex!=0
 +      && pLoop->u.btree.pIndex->aSortOrder[iEq]
      ){
        testcase( iEq==0 );
--      testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
--      testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
        testcase( bRev );
        bRev = !bRev;
      }
@@@ -3555,9 -4578,9 +3553,9 @@@ static Bitmask codeOneLoopStart
      ** If it is, jump to the next iteration of the loop.
      */
      r1 = sqlite3GetTempReg(pParse);
--    testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
--    testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
 -    if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
++    testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
++    testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
 +    if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
        sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
      }