]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Variable name changes in the query optimizer for disambiguation and
authordrh <drh@noemail.net>
Fri, 5 Dec 2008 02:36:33 +0000 (02:36 +0000)
committerdrh <drh@noemail.net>
Fri, 5 Dec 2008 02:36:33 +0000 (02:36 +0000)
clarification.  Clear space in boolean vectors for new bit values to
encode new query plan templates. (CVS 5980)

FossilOrigin-Name: 81bd0b5ce8a1cf057064c44e9b5371502cb8c58c

manifest
manifest.uuid
src/sqliteInt.h
src/where.c

index 3fcb6f54306e3c3fffa4188af5d38226073c0a0a..e798d580f8566f247bd4c81d95f49dfef68071b5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Expand\stable.*\sproperly\son\sa\sUSING\sor\sa\sNATURAL\sjoin.\s\sTicket\s#3522.\s(CVS\s5979)
-D 2008-12-05T00:00:07
+C Variable\sname\schanges\sin\sthe\squery\soptimizer\sfor\sdisambiguation\sand\nclarification.\s\sClear\sspace\sin\sboolean\svectors\sfor\snew\sbit\svalues\sto\nencode\snew\squery\splan\stemplates.\s(CVS\s5980)
+D 2008-12-05T02:36:34
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in f7e4c81c347b04f7b0f1c1b081a168645d7b8af7
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -155,7 +155,7 @@ F src/select.c e2127ce827914824c284046c66bf9259745b6be8
 F src/shell.c 838c745e7ac5c9fe17bc996224ed2f928d178bb2
 F src/sqlite.h.in b5d50f12fb9c7460a4ddfef8c1e799afaabefebf
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 1ed98f6df8475b82fed5bc174ebe1637dd9fc7d1
+F src/sqliteInt.h c8c99ad0d006f0e9957dc3e859ef53dd4a781a06
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
@@ -203,7 +203,7 @@ F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935
 F src/vdbemem.c 360396ac77b2da36a8cfc280e7c055482f0254e8
 F src/vtab.c 02c51eac45dbff1a1d6e73f58febf92ecb563f7f
 F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
-F src/where.c 96f7c2bd9e83c252d90ee2794f7a902fc5ba505b
+F src/where.c ef2a149bff7491207d84f825666c3d0e64e9692f
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 597662c5d777a122f9a3df0047ea5c5bd383a911
@@ -663,7 +663,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P cb0f1658d3db7ccf80843d66fa85af8de44710d0
-R 772817d081b9a8725e3ec2153391efbc
+P 06d206ef7d5e433ccde347d63dfcd2177545e1fd
+R 8d3d72064076a4415cfffcdda016269c
 U drh
-Z 0bfef847b98139757e4dba73ff4e74e2
+Z 95f6da2cc96e9f1bc5fb1f19dd7d6dc1
index e49fab9c6c0d1fa1b7efbb785478a4fe467cb1ab..f1f49e4b8193a2b7149194cdffec39ec6ba5868c 100644 (file)
@@ -1 +1 @@
-06d206ef7d5e433ccde347d63dfcd2177545e1fd
\ No newline at end of file
+81bd0b5ce8a1cf057064c44e9b5371502cb8c58c
\ No newline at end of file
index 0cd41f8d83aabca5f624b3f3602513eed2492be5..c03b6b476ca88016126496c5ec45b26564e8374c 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.800 2008/12/04 20:40:10 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.801 2008/12/05 02:36:34 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1517,7 +1517,7 @@ struct SrcList {
 */
 struct WhereLevel {
   int iFrom;            /* Which entry in the FROM clause */
-  int flags;            /* Flags associated with this level */
+  int wsFlags;          /* "Where-Scan Flags" associated with this level */
   int iMem;             /* First memory cell used by this level */
   int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
   Index *pIdx;          /* Index used.  NULL if no index */
@@ -1544,7 +1544,7 @@ struct WhereLevel {
 };
 
 /*
-** Flags appropriate for the wflags parameter of sqlite3WhereBegin().
+** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin().
 */
 #define WHERE_ORDERBY_NORMAL     0   /* No-op */
 #define WHERE_ORDERBY_MIN        1   /* ORDER BY processing for min() func */
index dae66c8e48c4e31f01353108980da37616ed8f56..6a56eca0f78edf39b7323ae8bdbc1813f5d1f68a 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.330 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: where.c,v 1.331 2008/12/05 02:36:34 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -72,20 +72,20 @@ typedef struct ExprMaskSet ExprMaskSet;
 */
 typedef struct WhereTerm WhereTerm;
 struct WhereTerm {
-  Expr *pExpr;            /* Pointer to the subexpression */
+  Expr *pExpr;            /* Pointer to the subexpression that is this term */
   i16 iParent;            /* Disable pWC->a[iParent] when this term disabled */
   i16 leftCursor;         /* Cursor number of X in "X <op> <expr>" */
   i16 leftColumn;         /* Column number of X in "X <op> <expr>" */
   u16 eOperator;          /* A WO_xx value describing <op> */
-  u8 flags;               /* Bit flags.  See below */
+  u8 wtFlags;             /* TERM_xxx bit flags.  See below */
   u8 nChild;              /* Number of children that must disable us */
   WhereClause *pWC;       /* The clause this term is part of */
-  Bitmask prereqRight;    /* Bitmask of tables used by pRight */
-  Bitmask prereqAll;      /* Bitmask of tables referenced by p */
+  Bitmask prereqRight;    /* Bitmask of tables used by pExpr->pRight */
+  Bitmask prereqAll;      /* Bitmask of tables referenced by pExpr */
 };
 
 /*
-** Allowed values of WhereTerm.flags
+** Allowed values of WhereTerm.wtFlags
 */
 #define TERM_DYNAMIC    0x01   /* Need to call sqlite3ExprDelete(db, pExpr) */
 #define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
@@ -143,38 +143,41 @@ struct ExprMaskSet {
 ** OR-ed combination of these values can be used when searching for
 ** terms in the where clause.
 */
-#define WO_IN     1
-#define WO_EQ     2
+#define WO_IN     0x001
+#define WO_EQ     0x002
 #define WO_LT     (WO_EQ<<(TK_LT-TK_EQ))
 #define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
 #define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
 #define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
-#define WO_MATCH  64
-#define WO_ISNULL 128
+#define WO_MATCH  0x040
+#define WO_ISNULL 0x080
+#define WO_OR     0x100
 
 /*
-** Value for flags returned by bestIndex().  
+** Value for wsFlags returned by bestIndex().  These flags determine which
+** search strategies are appropriate.
 **
-** The least significant byte is reserved as a mask for WO_ values above.
-** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
-** But if the table is the right table of a left join, WhereLevel.flags
-** is set to WO_IN|WO_EQ.  The WhereLevel.flags field can then be used as
+** The least significant 12 bits is reserved as a mask for WO_ values above.
+** The WhereLevel.wtFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
+** But if the table is the right table of a left join, WhereLevel.wtFlags
+** is set to WO_IN|WO_EQ.  The WhereLevel.wtFlags field can then be used as
 ** the "op" parameter to findTerm when we are resolving equality constraints.
 ** ISNULL constraints will then not be used on the right table of a left
 ** join.  Tickets #2177 and #2189.
 */
-#define WHERE_ROWID_EQ     0x000100   /* rowid=EXPR or rowid IN (...) */
-#define WHERE_ROWID_RANGE  0x000200   /* rowid<EXPR and/or rowid>EXPR */
-#define WHERE_COLUMN_EQ    0x001000   /* x=EXPR or x IN (...) */
-#define WHERE_COLUMN_RANGE 0x002000   /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN    0x004000   /* x IN (...) */
-#define WHERE_TOP_LIMIT    0x010000   /* x<EXPR or x<=EXPR constraint */
-#define WHERE_BTM_LIMIT    0x020000   /* x>EXPR or x>=EXPR constraint */
-#define WHERE_IDX_ONLY     0x080000   /* Use index only - omit table */
-#define WHERE_ORDERBY      0x100000   /* Output will appear in correct order */
-#define WHERE_REVERSE      0x200000   /* Scan in reverse order */
-#define WHERE_UNIQUE       0x400000   /* Selects no more than one row */
-#define WHERE_VIRTUALTABLE 0x800000   /* Use virtual-table processing */
+#define WHERE_ROWID_EQ     0x00001000  /* rowid=EXPR or rowid IN (...) */
+#define WHERE_ROWID_RANGE  0x00002000  /* rowid<EXPR and/or rowid>EXPR */
+#define WHERE_COLUMN_EQ    0x00010000  /* x=EXPR or x IN (...) */
+#define WHERE_COLUMN_RANGE 0x00020000  /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN    0x00040000  /* x IN (...) */
+#define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
+#define WHERE_IDX_ONLY     0x00800000  /* Use index only - omit table */
+#define WHERE_ORDERBY      0x01000000  /* Output will appear in correct order */
+#define WHERE_REVERSE      0x02000000  /* Scan in reverse order */
+#define WHERE_UNIQUE       0x04000000  /* Selects no more than one row */
+#define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
+#define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
 
 /*
 ** Initialize a preallocated WhereClause structure.
@@ -200,7 +203,7 @@ static void whereClauseClear(WhereClause *pWC){
   WhereTerm *a;
   sqlite3 *db = pWC->pParse->db;
   for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
-    if( a->flags & TERM_DYNAMIC ){
+    if( a->wtFlags & TERM_DYNAMIC ){
       sqlite3ExprDelete(db, a->pExpr);
     }
   }
@@ -213,7 +216,7 @@ static void whereClauseClear(WhereClause *pWC){
 ** Add a new entries to the WhereClause structure.  Increase the allocated
 ** space as necessary.
 **
-** If the flags argument includes TERM_DYNAMIC, then responsibility
+** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
 ** for freeing the expression p is assumed by the WhereClause object.
 **
 ** WARNING:  This routine might reallocate the space used to store
@@ -221,7 +224,7 @@ static void whereClauseClear(WhereClause *pWC){
 ** calling this routine.  Such pointers may be reinitialized by referencing
 ** the pWC->a[] array.
 */
-static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
+static int whereClauseInsert(WhereClause *pWC, Expr *p, int wtFlags){
   WhereTerm *pTerm;
   int idx;
   if( pWC->nTerm>=pWC->nSlot ){
@@ -229,7 +232,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
     sqlite3 *db = pWC->pParse->db;
     pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
     if( pWC->a==0 ){
-      if( flags & TERM_DYNAMIC ){
+      if( wtFlags & TERM_DYNAMIC ){
         sqlite3ExprDelete(db, p);
       }
       pWC->a = pOld;
@@ -244,7 +247,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
   pTerm = &pWC->a[idx = pWC->nTerm];
   pWC->nTerm++;
   pTerm->pExpr = p;
-  pTerm->flags = flags;
+  pTerm->wtFlags = wtFlags;
   pTerm->pWC = pWC;
   pTerm->iParent = -1;
   return idx;
@@ -421,10 +424,13 @@ static int operatorMask(int op){
     c = WO_IN;
   }else if( op==TK_ISNULL ){
     c = WO_ISNULL;
+  }else if( op==TK_OR ){
+    c = WO_OR;
   }else{
     c = WO_EQ<<(op-TK_EQ);
   }
   assert( op!=TK_ISNULL || c==WO_ISNULL );
+  assert( op!=TK_OR || c==WO_OR );
   assert( op!=TK_IN || c==WO_IN );
   assert( op!=TK_EQ || c==WO_EQ );
   assert( op!=TK_LT || c==WO_LT );
@@ -682,13 +688,13 @@ static int orTermIsOptCandidate(WhereTerm *pOrTerm, int iCursor, int iColumn){
 ** the duplicate has also been disqualified, return false.
 */
 static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){
-  if( pOrTerm->flags & TERM_COPIED ){
+  if( pOrTerm->wtFlags & TERM_COPIED ){
     /* This is the original term.  The duplicate is to the left had
     ** has not yet been analyzed and thus has not yet been disqualified. */
     return 1;
   }
-  if( (pOrTerm->flags & TERM_VIRTUAL)!=0
-     && (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){
+  if( (pOrTerm->wtFlags & TERM_VIRTUAL)!=0
+     && (pOr->a[pOrTerm->iParent].wtFlags & TERM_OR_OK)!=0 ){
     /* This is a duplicate term.  The original qualified so this one
     ** does not have to. */
     return 1;
@@ -781,7 +787,7 @@ static void exprAnalyze(
         pNew->iParent = idxTerm;
         pTerm = &pWC->a[idxTerm];
         pTerm->nChild = 1;
-        pTerm->flags |= TERM_COPIED;
+        pTerm->wtFlags |= TERM_COPIED;
       }else{
         pDup = pExpr;
         pNew = pTerm;
@@ -840,7 +846,7 @@ static void exprAnalyze(
     WhereClause sOr;
     WhereTerm *pOrTerm;
 
-    assert( (pTerm->flags & TERM_DYNAMIC)==0 );
+    assert( (pTerm->wtFlags & TERM_DYNAMIC)==0 );
     whereClauseInit(&sOr, pWC->pParse, pMaskSet);
     whereSplit(&sOr, pExpr, TK_OR);
     exprAnalyzeAll(pSrc, &sOr);
@@ -857,20 +863,20 @@ static void exprAnalyze(
           goto or_not_possible;
         }
         if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){
-          pOrTerm->flags |= TERM_OR_OK;
+          pOrTerm->wtFlags |= TERM_OR_OK;
         }else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){
-          pOrTerm->flags &= ~TERM_OR_OK;
+          pOrTerm->wtFlags &= ~TERM_OR_OK;
         }else{
           ok = 0;
         }
       }
-    }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 );
+    }while( !ok && (sOr.a[j++].wtFlags & TERM_COPIED)!=0 && j<2 );
     if( ok ){
       ExprList *pList = 0;
       Expr *pNew, *pDup;
       Expr *pLeft = 0;
       for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0; i--, pOrTerm++){
-        if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
+        if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
         pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
         pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
         pLeft = pOrTerm->pExpr->pLeft;
@@ -977,7 +983,7 @@ or_not_possible:
       pNewTerm->iParent = idxTerm;
       pTerm = &pWC->a[idxTerm];
       pTerm->nChild = 1;
-      pTerm->flags |= TERM_COPIED;
+      pTerm->wtFlags |= TERM_COPIED;
       pNewTerm->prereqAll = pTerm->prereqAll;
     }
   }
@@ -1486,23 +1492,23 @@ static double bestIndex(
   Bitmask notReady,           /* Mask of cursors that are not available */
   ExprList *pOrderBy,         /* The order by clause */
   Index **ppIndex,            /* Make *ppIndex point to the best index */
-  int *pFlags,                /* Put flags describing this choice in *pFlags */
+  int *pWsFlags,              /* Put wsFlags describing scan strategy here */
   int *pnEq                   /* Put the number of == or IN constraints here */
 ){
   WhereTerm *pTerm;
   Index *bestIdx = 0;         /* Index that gives the lowest cost */
   double lowestCost;          /* The cost of using bestIdx */
-  int bestFlags = 0;          /* Flags associated with bestIdx */
+  int bestWsFlags = 0;        /* Flags associated with bestIdx */
   int bestNEq = 0;            /* Best value for nEq */
   int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
   Index *pProbe;              /* An index we are evaluating */
   int rev;                    /* True to scan in reverse order */
-  int flags;                  /* Flags associated with pProbe */
+  int wsFlags;                /* Flags associated with pProbe */
   int nEq;                    /* Number of == or IN constraints */
   int eqTermMask;             /* Mask of valid equality operators */
   double cost;                /* Cost of using pProbe */
 
-  WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName, notReady));
+  WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName,notReady));
   lowestCost = SQLITE_BIG_DBL;
   pProbe = pSrc->pTab->pIndex;
   if( pSrc->notIndexed ){
@@ -1518,7 +1524,7 @@ static double bestIndex(
   if( pProbe==0 &&
      findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
      (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
-    *pFlags = 0;
+    *pWsFlags = 0;
     *ppIndex = 0;
     *pnEq = 0;
     return 0.0;
@@ -1532,11 +1538,11 @@ static double bestIndex(
     if( pTerm ){
       Expr *pExpr;
       *ppIndex = 0;
-      bestFlags = WHERE_ROWID_EQ;
+      bestWsFlags = WHERE_ROWID_EQ;
       if( pTerm->eOperator & WO_EQ ){
         /* Rowid== is always the best pick.  Look no further.  Because only
         ** a single row is generated, output is always in sorted order */
-        *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
+        *pWsFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
         *pnEq = 1;
         WHERETRACE(("... best is rowid\n"));
         return 0.0;
@@ -1559,32 +1565,32 @@ static double bestIndex(
     */
     cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
     WHERETRACE(("... table scan base cost: %.9g\n", cost));
-    flags = WHERE_ROWID_RANGE;
+    wsFlags = WHERE_ROWID_RANGE;
   
     /* Check for constraints on a range of rowids in a table scan.
     */
     pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
     if( pTerm ){
       if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
-        flags |= WHERE_TOP_LIMIT;
+        wsFlags |= WHERE_TOP_LIMIT;
         cost /= 3;  /* Guess that rowid<EXPR eliminates two-thirds or rows */
       }
       if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
-        flags |= WHERE_BTM_LIMIT;
+        wsFlags |= WHERE_BTM_LIMIT;
         cost /= 3;  /* Guess that rowid>EXPR eliminates two-thirds of rows */
       }
       WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
     }else{
-      flags = 0;
+      wsFlags = 0;
     }
   
     /* If the table scan does not satisfy the ORDER BY clause, increase
     ** the cost by NlogN to cover the expense of sorting. */
     if( pOrderBy ){
       if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
-        flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
+        wsFlags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
         if( rev ){
-          flags |= WHERE_REVERSE;
+          wsFlags |= WHERE_REVERSE;
         }
       }else{
         cost += cost*estLog(cost);
@@ -1593,7 +1599,7 @@ static double bestIndex(
     }
     if( cost<lowestCost ){
       lowestCost = cost;
-      bestFlags = flags;
+      bestWsFlags = wsFlags;
     }
   }
 
@@ -1622,15 +1628,15 @@ static double bestIndex(
     /* Count the number of columns in the index that are satisfied
     ** by x=EXPR constraints or x IN (...) constraints.
     */
-    flags = 0;
+    wsFlags = 0;
     for(i=0; i<pProbe->nColumn; i++){
       int j = pProbe->aiColumn[i];
       pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe);
       if( pTerm==0 ) break;
-      flags |= WHERE_COLUMN_EQ;
+      wsFlags |= WHERE_COLUMN_EQ;
       if( pTerm->eOperator & WO_IN ){
         Expr *pExpr = pTerm->pExpr;
-        flags |= WHERE_COLUMN_IN;
+        wsFlags |= WHERE_COLUMN_IN;
         if( pExpr->pSelect!=0 ){
           inMultiplier *= 25;
         }else if( ALWAYS(pExpr->pList) ){
@@ -1640,9 +1646,9 @@ static double bestIndex(
     }
     cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier);
     nEq = i;
-    if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0
+    if( pProbe->onError!=OE_None && (wsFlags & WHERE_COLUMN_IN)==0
          && nEq==pProbe->nColumn ){
-      flags |= WHERE_UNIQUE;
+      wsFlags |= WHERE_UNIQUE;
     }
     WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n",nEq,inMultiplier,cost));
 
@@ -1652,13 +1658,13 @@ static double bestIndex(
       int j = pProbe->aiColumn[nEq];
       pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe);
       if( pTerm ){
-        flags |= WHERE_COLUMN_RANGE;
+        wsFlags |= WHERE_COLUMN_RANGE;
         if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){
-          flags |= WHERE_TOP_LIMIT;
+          wsFlags |= WHERE_TOP_LIMIT;
           cost /= 3;
         }
         if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){
-          flags |= WHERE_BTM_LIMIT;
+          wsFlags |= WHERE_BTM_LIMIT;
           cost /= 3;
         }
         WHERETRACE(("...... range reduces cost to %.9g\n", cost));
@@ -1668,14 +1674,14 @@ static double bestIndex(
     /* Add the additional cost of sorting if that is a factor.
     */
     if( pOrderBy ){
-      if( (flags & WHERE_COLUMN_IN)==0 &&
+      if( (wsFlags & WHERE_COLUMN_IN)==0 &&
            isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
-        if( flags==0 ){
-          flags = WHERE_COLUMN_RANGE;
+        if( wsFlags==0 ){
+          wsFlags = WHERE_COLUMN_RANGE;
         }
-        flags |= WHERE_ORDERBY;
+        wsFlags |= WHERE_ORDERBY;
         if( rev ){
-          flags |= WHERE_REVERSE;
+          wsFlags |= WHERE_REVERSE;
         }
       }else{
         cost += cost*estLog(cost);
@@ -1687,7 +1693,7 @@ static double bestIndex(
     ** ever reading the table.  If that is the case, then halve the
     ** cost of this index.
     */
-    if( flags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
+    if( wsFlags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
       Bitmask m = pSrc->colUsed;
       int j;
       for(j=0; j<pProbe->nColumn; j++){
@@ -1697,7 +1703,7 @@ static double bestIndex(
         }
       }
       if( m==0 ){
-        flags |= WHERE_IDX_ONLY;
+        wsFlags |= WHERE_IDX_ONLY;
         cost /= 2;
         WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost));
       }
@@ -1705,10 +1711,10 @@ static double bestIndex(
 
     /* If this index has achieved the lowest cost so far, then use it.
     */
-    if( flags && cost < lowestCost ){
+    if( wsFlags && cost < lowestCost ){
       bestIdx = pProbe;
       lowestCost = cost;
-      bestFlags = flags;
+      bestWsFlags = wsFlags;
       bestNEq = nEq;
     }
   }
@@ -1716,9 +1722,9 @@ static double bestIndex(
   /* Report the best result
   */
   *ppIndex = bestIdx;
-  WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
-        bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
-  *pFlags = bestFlags | eqTermMask;
+  WHERETRACE(("best index is %s, cost=%.9g, wsFlags=%x, nEq=%d\n",
+        bestIdx ? bestIdx->zName : "(none)", lowestCost, bestWsFlags, bestNEq));
+  *pWsFlags = bestWsFlags | eqTermMask;
   *pnEq = bestNEq;
   return lowestCost;
 }
@@ -1749,10 +1755,10 @@ static double bestIndex(
 */
 static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
   if( pTerm
-      && ALWAYS((pTerm->flags & TERM_CODED)==0)
+      && ALWAYS((pTerm->wtFlags & TERM_CODED)==0)
       && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
   ){
-    pTerm->flags |= TERM_CODED;
+    pTerm->wtFlags |= TERM_CODED;
     if( pTerm->iParent>=0 ){
       WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
       if( (--pOther->nChild)==0 ){
@@ -1894,9 +1900,9 @@ static int codeAllEqualityTerms(
   for(j=0; j<nEq; j++){
     int r1;
     int k = pIdx->aiColumn[j];
-    pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
+    pTerm = findTerm(pWC, iCur, k, notReady, pLevel->wsFlags, pIdx);
     if( NEVER(pTerm==0) ) break;
-    assert( (pTerm->flags & TERM_CODED)==0 );
+    assert( (pTerm->wtFlags & TERM_CODED)==0 );
     r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
     if( r1!=regBase+j ){
       sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
@@ -2034,7 +2040,7 @@ WhereInfo *sqlite3WhereBegin(
   SrcList *pTabList,    /* A list of all tables to be scanned */
   Expr *pWhere,         /* The WHERE clause */
   ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
-  u8 wflags             /* One of the WHERE_* flags defined in sqliteInt.h */
+  u8 wctrlFlags         /* One of the WHERE_* flags defined in sqliteInt.h */
 ){
   int i;                     /* Loop counter */
   WhereInfo *pWInfo;         /* Will become the return value of this function */
@@ -2047,7 +2053,7 @@ WhereInfo *sqlite3WhereBegin(
   struct SrcList_item *pTabItem;  /* A single entry from pTabList */
   WhereLevel *pLevel;             /* A single level in the pWInfo list */
   int iFrom;                      /* First unused FROM clause element */
-  int andFlags;              /* AND-ed combination of all wc.a[].flags */
+  int andFlags;              /* AND-ed combination of all wc.a[].wtFlags */
   sqlite3 *db;               /* Database connection */
   ExprList *pOrderBy = 0;
 
@@ -2133,7 +2139,7 @@ WhereInfo *sqlite3WhereBegin(
   ** This loop fills in the following fields:
   **
   **   pWInfo->a[].pIdx      The index to use for this level of the loop.
-  **   pWInfo->a[].flags     WHERE_xxx flags associated with pIdx
+  **   pWInfo->a[].wsFlags   WHERE_xxx flags associated with pIdx
   **   pWInfo->a[].nEq       The number of == and IN constraints
   **   pWInfo->a[].iFrom     Which term of the FROM clause is being coded
   **   pWInfo->a[].iTabCur   The VDBE cursor for the database table
@@ -2149,12 +2155,12 @@ WhereInfo *sqlite3WhereBegin(
   WHERETRACE(("*** Optimizer Start ***\n"));
   for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
     Index *pIdx;                /* Index for FROM table at pTabItem */
-    int flags;                  /* Flags asssociated with pIdx */
+    int wsFlags;                /* Flags describing scan strategy */
     int nEq;                    /* Number of == or IN constraints */
     double cost;                /* The cost for pIdx */
     int j;                      /* For looping over FROM tables */
     Index *pBest = 0;           /* The best index seen so far */
-    int bestFlags = 0;          /* Flags associated with pBest */
+    int bestWsFlags = 0;        /* Flags associated with pBest */
     int bestNEq = 0;            /* nEq associated with pBest */
     double lowestCost;          /* Cost of the pBest */
     int bestJ = 0;              /* The value of j */
@@ -2180,10 +2186,10 @@ WhereInfo *sqlite3WhereBegin(
         cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
                                 ppOrderBy ? *ppOrderBy : 0, i==0,
                                 ppIdxInfo);
-        flags = WHERE_VIRTUALTABLE;
+        wsFlags = WHERE_VIRTUALTABLE;
         pIndex = *ppIdxInfo;
         if( pIndex && pIndex->orderByConsumed ){
-          flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
+          wsFlags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
         }
         pIdx = 0;
         nEq = 0;
@@ -2200,14 +2206,14 @@ WhereInfo *sqlite3WhereBegin(
       {
         cost = bestIndex(pParse, &wc, pTabItem, notReady,
                          (i==0 && ppOrderBy) ? *ppOrderBy : 0,
-                         &pIdx, &flags, &nEq);
+                         &pIdx, &wsFlags, &nEq);
         pIndex = 0;
       }
       if( cost<lowestCost ){
         once = 1;
         lowestCost = cost;
         pBest = pIdx;
-        bestFlags = flags;
+        bestWsFlags = wsFlags;
         bestNEq = nEq;
         bestJ = j;
         pLevel->pBestIdx = pIndex;
@@ -2216,11 +2222,11 @@ WhereInfo *sqlite3WhereBegin(
     }
     WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ,
            pLevel-pWInfo->a));
-    if( (bestFlags & WHERE_ORDERBY)!=0 ){
+    if( (bestWsFlags & WHERE_ORDERBY)!=0 ){
       *ppOrderBy = 0;
     }
-    andFlags &= bestFlags;
-    pLevel->flags = bestFlags;
+    andFlags &= bestWsFlags;
+    pLevel->wsFlags = bestWsFlags;
     pLevel->pIdx = pBest;
     pLevel->nEq = bestNEq;
     pLevel->aInLoop = 0;
@@ -2259,10 +2265,10 @@ WhereInfo *sqlite3WhereBegin(
   ** The one-pass algorithm only works if the WHERE clause constraints
   ** the statement to update a single row.
   */
-  assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
-  if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+  assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
+  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
     pWInfo->okOnePass = 1;
-    pWInfo->a[0].flags &= ~WHERE_IDX_ONLY;
+    pWInfo->a[0].wsFlags &= ~WHERE_IDX_ONLY;
   }
 
   /* Open all tables in the pTabList and any indices selected for
@@ -2285,7 +2291,7 @@ WhereInfo *sqlite3WhereBegin(
       }
       if( (pIx = pLevel->pIdx)!=0 ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName);
-      }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+      }else if( pLevel->wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
       }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -2295,7 +2301,7 @@ WhereInfo *sqlite3WhereBegin(
                     pBestIdx->idxNum, pBestIdx->idxStr);
       }
 #endif
-      if( pLevel->flags & WHERE_ORDERBY ){
+      if( pLevel->wsFlags & WHERE_ORDERBY ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
       }
       sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC);
@@ -2312,7 +2318,7 @@ WhereInfo *sqlite3WhereBegin(
                         (const char*)pTab->pVtab, P4_VTAB);
     }else
 #endif
-    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
+    if( (pLevel->wsFlags & WHERE_IDX_ONLY)==0 ){
       int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
       sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
       if( !pWInfo->okOnePass && pTab->nCol<BMS ){
@@ -2356,8 +2362,8 @@ WhereInfo *sqlite3WhereBegin(
     iCur = pTabItem->iCursor;
     pIdx = pLevel->pIdx;
     iIdxCur = pLevel->iIdxCur;
-    bRev = (pLevel->flags & WHERE_REVERSE)!=0;
-    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
+    bRev = (pLevel->wsFlags & WHERE_REVERSE)!=0;
+    omitTable = (pLevel->wsFlags & WHERE_IDX_ONLY)!=0;
 
     /* Create labels for the "break" and "continue" instructions
     ** for the current loop.  Jump to brk to break out of a loop.
@@ -2430,7 +2436,7 @@ WhereInfo *sqlite3WhereBegin(
     }else
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
-    if( pLevel->flags & WHERE_ROWID_EQ ){
+    if( pLevel->wsFlags & WHERE_ROWID_EQ ){
       /* Case 1:  We can directly reference a single row using an
       **          equality comparison against the ROWID field.  Or
       **          we reference multiple rows using a "rowid IN (...)"
@@ -2450,7 +2456,7 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3ReleaseTempReg(pParse, rtmp);
       VdbeComment((v, "pk"));
       pLevel->op = OP_Noop;
-    }else if( pLevel->flags & WHERE_ROWID_RANGE ){
+    }else if( pLevel->wsFlags & WHERE_ROWID_RANGE ){
       /* Case 2:  We have an inequality comparison against the ROWID field.
       */
       int testOp = OP_Noop;
@@ -2517,7 +2523,7 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
         sqlite3ReleaseTempReg(pParse, r1);
       }
-    }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
+    }else if( pLevel->wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
       /* Case 3: A scan using an index.
       **
       **         The WHERE clause may contain zero or more equality 
@@ -2592,8 +2598,8 @@ WhereInfo *sqlite3WhereBegin(
       ** the first one after the nEq equality constraints in the index,
       ** this requires some special handling.
       */
-      if( (wflags&WHERE_ORDERBY_MIN)!=0
-       && (pLevel->flags&WHERE_ORDERBY)
+      if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
+       && (pLevel->wsFlags&WHERE_ORDERBY)
        && (pIdx->nColumn>nEq)
       ){
         assert( pOrderBy->nExpr==1 );
@@ -2604,10 +2610,10 @@ WhereInfo *sqlite3WhereBegin(
       /* Find any inequality constraint terms for the start and end 
       ** of the range. 
       */
-      if( pLevel->flags & WHERE_TOP_LIMIT ){
+      if( pLevel->wsFlags & WHERE_TOP_LIMIT ){
         pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
       }
-      if( pLevel->flags & WHERE_BTM_LIMIT ){
+      if( pLevel->wsFlags & WHERE_BTM_LIMIT ){
         pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
       }
 
@@ -2684,9 +2690,9 @@ WhereInfo *sqlite3WhereBegin(
       ** If it is, jump to the next iteration of the loop.
       */
       r1 = sqlite3GetTempReg(pParse);
-      testcase( pLevel->flags & WHERE_BTM_LIMIT );
-      testcase( pLevel->flags & WHERE_TOP_LIMIT );
-      if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
+      testcase( pLevel->wsFlags & WHERE_BTM_LIMIT );
+      testcase( pLevel->wsFlags & WHERE_TOP_LIMIT );
+      if( pLevel->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
         sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
         sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
       }
@@ -2724,9 +2730,9 @@ WhereInfo *sqlite3WhereBegin(
     k = 0;
     for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
       Expr *pE;
-      testcase( pTerm->flags & TERM_VIRTUAL );
-      testcase( pTerm->flags & TERM_CODED );
-      if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+      testcase( pTerm->wtFlags & TERM_VIRTUAL );
+      testcase( pTerm->wtFlags & TERM_CODED );
+      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
       if( (pTerm->prereqAll & notReady)!=0 ) continue;
       pE = pTerm->pExpr;
       assert( pE!=0 );
@@ -2737,7 +2743,7 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3ExprIfFalse(pParse, pE, cont, SQLITE_JUMPIFNULL);
       pParse->disableColCache -= k;
       k = 1;
-      pTerm->flags |= TERM_CODED;
+      pTerm->wtFlags |= TERM_CODED;
     }
 
     /* For a LEFT OUTER JOIN, generate code that will record the fact that
@@ -2750,13 +2756,13 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur);
       sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur);
       for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
-        testcase( pTerm->flags & TERM_VIRTUAL );
-        testcase( pTerm->flags & TERM_CODED );
-        if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+        testcase( pTerm->wtFlags & TERM_VIRTUAL );
+        testcase( pTerm->wtFlags & TERM_CODED );
+        if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
         if( (pTerm->prereqAll & notReady)!=0 ) continue;
         assert( pTerm->pExpr );
         sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL);
-        pTerm->flags |= TERM_CODED;
+        pTerm->wtFlags |= TERM_CODED;
       }
     }
   }
@@ -2777,7 +2783,7 @@ WhereInfo *sqlite3WhereBegin(
     if( z==0 ) z = pTabItem->pTab->zName;
     n = strlen(z);
     if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
-      if( pLevel->flags & WHERE_IDX_ONLY ){
+      if( pLevel->wsFlags & WHERE_IDX_ONLY ){
         memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
         nQPlan += 2;
       }else{
@@ -2786,9 +2792,9 @@ WhereInfo *sqlite3WhereBegin(
       }
       sqlite3_query_plan[nQPlan++] = ' ';
     }
-    testcase( pLevel->flags & WHERE_ROWID_EQ );
-    testcase( pLevel->flags & WHERE_ROWID_RANGE );
-    if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+    testcase( pLevel->wsFlags & WHERE_ROWID_EQ );
+    testcase( pLevel->wsFlags & WHERE_ROWID_RANGE );
+    if( pLevel->wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
       memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
       nQPlan += 2;
     }else if( pLevel->pIdx==0 ){
@@ -2882,7 +2888,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
-    if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
+    if( !pWInfo->okOnePass && (pLevel->wsFlags & WHERE_IDX_ONLY)==0 ){
       sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
     }
     if( pLevel->pIdx!=0 ){
@@ -2906,7 +2912,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       int k, j, last;
       VdbeOp *pOp;
       Index *pIdx = pLevel->pIdx;
-      int useIndexOnly = pLevel->flags & WHERE_IDX_ONLY;
+      int useIndexOnly = pLevel->wsFlags & WHERE_IDX_ONLY;
 
       assert( pIdx!=0 );
       pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);