]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Split the OP_Integer opcode into OP_Integer and OP_Int64. This allows
authordrh <drh@noemail.net>
Thu, 21 Jul 2005 18:23:20 +0000 (18:23 +0000)
committerdrh <drh@noemail.net>
Thu, 21 Jul 2005 18:23:20 +0000 (18:23 +0000)
comments to be added to OP_Integer.  Cleanup in the optimizer.  Allow
terms of the FROM clause to be reordered automatically. (CVS 2556)

FossilOrigin-Name: e2f822ac82d0a5a59de0b63cce65d4fd6c178ff1

manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/sqliteInt.h
src/update.c
src/vdbe.c
src/where.c

index 684d41d12fc185f17d27f85f637539abd5b0ce5e..1bdabd69065e23f6304753109f23bb46dceb5f68 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\scomments\sto\stest\scases.\s\sImprovements\sto\sthe\squery\splan\stest\svariable.\s(CVS\s2555)
-D 2005-07-21T03:48:20
+C Split\sthe\sOP_Integer\sopcode\sinto\sOP_Integer\sand\sOP_Int64.\s\sThis\sallows\ncomments\sto\sbe\sadded\sto\sOP_Integer.\s\sCleanup\sin\sthe\soptimizer.\s\sAllow\nterms\sof\sthe\sFROM\sclause\sto\sbe\sreordered\sautomatically.\s(CVS\s2556)
+D 2005-07-21T18:23:20
 F Makefile.in 22ea9c0fe748f591712d8fe3c6d972c6c173a165
 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -33,16 +33,16 @@ F src/attach.c 3615dbe960cbee4aa5ea300b8a213dad36527b0f
 F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
 F src/btree.c ec55bd70052cdd0958f3a0e79ad58d93561acb20
 F src/btree.h 41a71ce027db9ddee72cb43df2316bbe3a1d92af
-F src/build.c a908365b4f900096f406f9028181550f818f59fd
+F src/build.c c2b9379e3b51775de01137a68d3a67359e29d3aa
 F src/callback.c 0910b611e0c158f107ee3ff86f8a371654971e2b
 F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
-F src/delete.c 250d436a68fe371b4ab403d1c0f6fdc9a6860c39
+F src/delete.c be1fc25c9e109cd8cbab42a43ee696263da7c04b
 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
-F src/expr.c cf5146e8a0a1ce7261ac2f9ecb15e99eb98de7ac
+F src/expr.c 0e158f7cc8df562320faa9f2de48cfd856458a52
 F src/func.c 2be0799df0c05066a29e589485ebee0b3f756a15
 F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
-F src/insert.c c4533240451b73ead88098b5d819cb70fa0880bd
+F src/insert.c 484c73bc1309f283a31baa0e114f3ee980536397
 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
 F src/main.c 568005dc335c17bf1f7ce346652c1c505f412fd7
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
@@ -64,7 +64,7 @@ F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4
 F src/select.c c611471052773b94af771693686bd5bcdbbb0dba
 F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26
 F src/sqlite.h.in 838382ed6b48d392366a55e07f49d9d71263e1fe
-F src/sqliteInt.h a3252616131187e227268fc405c8c536b3be9fac
+F src/sqliteInt.h 89ace2d46348c2924368ff97d41adec5cacacfdc
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
 F src/tclsqlite.c cccaf6b78c290d824cf8ea089b8b27377e545830
 F src/test1.c 722c1444b5774705eb6eb11163343fc94ffe17f7
@@ -74,18 +74,18 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
 F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
 F src/tokenize.c 57ec9926612fb9e325b57a141303573bc20c79bf
 F src/trigger.c f51dec15921629591cb98bf2e350018e268b109a
-F src/update.c 49a9c618c3ba1ca57038d9ce41f14e958442fe58
+F src/update.c a9d2c5f504212d62da1b094476f1389c0e02f83f
 F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 F src/util.c 668d31be592753e5b8ea00e69ea8d3eedb29fa22
 F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
-F src/vdbe.c 7b41a1979d3421dbbe34a3a48970b4e75fb1d634
+F src/vdbe.c aa8b8d30aa5b1b046a6a5acf502370a064581e09
 F src/vdbe.h 75e466d84d362b0c4498978a9d6b1e6bd32ecf3b
 F src/vdbeInt.h 9be9a6c43d38124bd03cc5cf05715605b1789fd9
 F src/vdbeapi.c 7f392f0792d1258c958083d7de9eae7c3530c9a6
 F src/vdbeaux.c 3732a86566a6be4da4c606e9334baf3fd98667af
 F src/vdbefifo.c b8805850afe13b43f1de78d58088cb5d66f88e1e
 F src/vdbemem.c da8e8d6f29dd1323f782f000d7cd120027c9ff03
-F src/where.c 9e5bd5f1ab83a2d55c9e84a7e6613602b477e328
+F src/where.c 65d9b27edaf29edaba95442f65a3cfc36ae6dbdb
 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
@@ -286,7 +286,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
-P c30cbba9ead1b4d07f225b1e8a65d5d5230ea45d
-R ce3457bbcec9a76540a332d37f4098ee
+P ef3a157f469d72cbd2f713f997598ddf47f340d2
+R 36cfab460ee644fb8d42d82df874b83c
 U drh
-Z a55f9e28ea4b33602aa900e8cfaf2b57
+Z b75bf1e0203a3ee4b4ae420ba35e8ecb
index c2fac60364b1d80efbeee6d3a4cae0f124aa5955..0e108c626c1f3a33dedb319bff924e7140147afb 100644 (file)
@@ -1 +1 @@
-ef3a157f469d72cbd2f713f997598ddf47f340d2
\ No newline at end of file
+e2f822ac82d0a5a59de0b63cce65d4fd6c178ff1
\ No newline at end of file
index 3ad25d1d142db196f487422cd1af1c40ec4ccf63..25b441454c38f3b43a7aa0bb4b259b24775fae46 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.331 2005/07/21 03:15:00 drh Exp $
+** $Id: build.c,v 1.332 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1999,9 +1999,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);
   sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
                     (char*)&pIndex->keyInfo, P3_KEYINFO);
-  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);
-  sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);
+  sqlite3OpenTableForReading(v, iTab, pTab);
   addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
   sqlite3GenerateIndexKey(v, pIndex, iTab);
   if( pIndex->onError!=OE_None ){
@@ -2601,7 +2599,6 @@ void sqlite3SrcListDelete(SrcList *pList){
     sqlite3SelectDelete(pItem->pSelect);
     sqlite3ExprDelete(pItem->pOn);
     sqlite3IdListDelete(pItem->pUsing);
-    sqlite3WhereIdxListDelete(pItem->pWIdx);
   }
   sqliteFree(pList);
 }
index faf0f2fc812fa311ff2101879a495c0d48379453..8db7a8ad10faf18481ce9b2d2623aa9ef70ff9fd 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.108 2005/07/08 13:08:00 drh Exp $
+** $Id: delete.c,v 1.109 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -65,8 +65,8 @@ void sqlite3OpenTableForReading(
   Table *pTab     /* The table to be opened */
 ){
   sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
   VdbeComment((v, "# %s", pTab->zName));
+  sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
 }
 
index 5f797029f46b6f1a78ce792942075f12d89e7f28..6da0289b35e92cb9196eafee00f4eea383c98385 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.212 2005/07/21 03:15:00 drh Exp $
+** $Id: expr.c,v 1.213 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -489,7 +489,6 @@ SrcList *sqlite3SrcListDup(SrcList *p){
     pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
     pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
     pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing);
-    pNewItem->pWIdx = 0;
     pNewItem->colUsed = pOldItem->colUsed;
   }
   return pNew;
@@ -1398,7 +1397,7 @@ static void codeInteger(Vdbe *v, const char *z, int n){
   if( sqlite3GetInt32(z, &i) ){
     sqlite3VdbeAddOp(v, OP_Integer, i, 0);
   }else if( sqlite3FitsIn64Bits(z) ){
-    sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n);
+    sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
   }else{
     sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
   }
index b236a10a268e6c8de4caeae3a02e006aac61f332..428c8cd125aeaa04b6f780d24e8f987b253f172d 100644 (file)
@@ -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.141 2005/07/08 17:13:47 drh Exp $
+** $Id: insert.c,v 1.142 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1096,11 +1096,12 @@ void sqlite3OpenTableAndIndices(
   Vdbe *v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, op, base, pTab->tnum);
   VdbeComment((v, "# %s", pTab->zName));
+  sqlite3VdbeAddOp(v, op, base, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
   for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
+    VdbeComment((v, "# %s", pIdx->zName));
     sqlite3VdbeOp3(v, op, i+base, pIdx->tnum,
                    (char*)&pIdx->keyInfo, P3_KEYINFO);
   }
index 3425008c51ff0697b0a45316480db1e43e1e1b00..1883a4dfb47169ac2452f5d1d68f3f7ec07e8554 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.395 2005/07/21 03:15:00 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.396 2005/07/21 18:23:20 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -320,7 +320,6 @@ typedef struct Token Token;
 typedef struct TriggerStack TriggerStack;
 typedef struct TriggerStep TriggerStep;
 typedef struct Trigger Trigger;
-typedef struct WhereIdx WhereIdx;
 typedef struct WhereInfo WhereInfo;
 typedef struct WhereLevel WhereLevel;
 
@@ -929,7 +928,6 @@ struct SrcList {
     i16 iCursor;      /* The VDBE cursor number used to access this table */
     Expr *pOn;        /* The ON clause of a join */
     IdList *pUsing;   /* The USING clause of a join */
-    WhereIdx *pWIdx;  /* List of structures used by the optimizer */
     Bitmask colUsed;  /* Bit N (1<<N) set if column N or pTab is used */
   } a[1];             /* One entry for each identifier on the list */
 };
@@ -951,17 +949,18 @@ struct SrcList {
 ** access or modified by other modules.
 */
 struct WhereLevel {
-  int iMem;            /* Memory cell used by this level */
-  Index *pIdx;         /* Index used.  NULL if no index */
-  int iTabCur;         /* The VDBE cursor used to access the table */
-  int iIdxCur;         /* The VDBE cursor used to acesss pIdx */
-  int brk;             /* Jump here to break out of the loop */
-  int cont;            /* Jump here to continue with the next loop cycle */
-  int op, p1, p2;      /* Opcode used to terminate the loop */
-  int iLeftJoin;       /* Memory cell used to implement LEFT OUTER JOIN */
-  int top;             /* First instruction of interior of the loop */
-  int inOp, inP1, inP2;/* Opcode used to implement an IN operator */
-  int flags;           /* Flags associated with this level */
+  int iFrom;            /* Which entry in the FROM clause */
+  int flags;            /* Flags associated with this level */
+  int iMem;             /* Memory cell used by this level */
+  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
+  Index *pIdx;          /* Index used.  NULL if no index */
+  int iTabCur;          /* The VDBE cursor used to access the table */
+  int iIdxCur;          /* The VDBE cursor used to acesss pIdx */
+  int brk;              /* Jump here to break out of the loop */
+  int cont;             /* Jump here to continue with the next loop cycle */
+  int top;              /* First instruction of interior of the loop */
+  int op, p1, p2;       /* Opcode used to terminate the loop */
+  int inOp, inP1, inP2; /* Opcode used to implement an IN operator */
 };
 
 /*
@@ -1569,7 +1568,6 @@ CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
 char sqlite3AffinityType(const Token*);
 void sqlite3Analyze(Parse*, Token*, Token*);
 int sqlite3InvokeBusyHandler(BusyHandler*);
-void sqlite3WhereIdxListDelete(WhereIdx*);
 
 #ifdef SQLITE_SSE
 #include "sseInt.h"
index 0ff9eb732d430962e2f189a76b39b4c8c36c8360..99900be8b31416cd55a71459cc7acb503808d761 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.109 2005/07/08 13:08:00 drh Exp $
+** $Id: update.c,v 1.110 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -47,7 +47,11 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
     u8 enc = sqlite3VdbeDb(v)->enc;
     Column *pCol = &pTab->aCol[i];
     sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
-    sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
+    if( pValue ){
+      sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
+    }else{
+      VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
+    }
   }
 }
 
index f6afbe027d328dc8ffba149b4d5405719b88bfce..79292ec94433f4e7c280e21277d47318e443ff15 100644 (file)
@@ -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.475 2005/07/09 02:16:03 drh Exp $
+** $Id: vdbe.c,v 1.476 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -670,28 +670,31 @@ case OP_Halt: {            /* no-push */
   return p->rc ? SQLITE_ERROR : SQLITE_DONE;
 }
 
-/* Opcode: Integer P1 * P3
+/* Opcode: Integer P1 * *
 **
-** The integer value P1 is pushed onto the stack.  If P3 is not zero
-** then it is assumed to be a string representation of the same integer.
-** If P1 is zero and P3 is not zero, then the value is derived from P3.
-**
-** If the value cannot be represented as a 32-bits then its value
-** will be in P3.
+** The 32-bit integer value P1 is pushed onto the stack.
 */
 case OP_Integer: {
   pTos++;
-  if( pOp->p3==0 ){
-    pTos->flags = MEM_Int;
-    pTos->i = pOp->p1;
-  }else{
-    pTos->flags = MEM_Str|MEM_Static|MEM_Term;
-    pTos->z = pOp->p3;
-    pTos->n = strlen(pTos->z);
-    pTos->enc = SQLITE_UTF8;
-    pTos->i = sqlite3VdbeIntValue(pTos);
-    pTos->flags |= MEM_Int;
-  }
+  pTos->flags = MEM_Int;
+  pTos->i = pOp->p1;
+  break;
+}
+
+/* Opcode: Int64 * * P3
+**
+** P3 is a string representation of an integer.  Convert that integer
+** to a 64-bit value and push it onto the stack.
+*/
+case OP_Int64: {
+  pTos++;
+  assert( pOp->p3!=0 );
+  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
+  pTos->z = pOp->p3;
+  pTos->n = strlen(pTos->z);
+  pTos->enc = SQLITE_UTF8;
+  pTos->i = sqlite3VdbeIntValue(pTos);
+  pTos->flags |= MEM_Int;
   break;
 }
 
@@ -1828,6 +1831,13 @@ case OP_SetNumColumns: {       /* no-push */
 ** just a pointer into the record which is stored further down on the
 ** stack.  The column value is not copied. The number of columns in the
 ** record is stored on the stack just above the record itself.
+**
+** If the column contains fewer than P2 fields, then push a NULL.  Or
+** if P3 is of type P3_MEM, then push the P3 value.  The P3 value will
+** be default value for a column that has been added using the ALTER TABLE
+** ADD COLUMN command.  If P3 is an ordinary string, just push a NULL.
+** When P3 is a string it is really just a comment describing the value
+** to be pushed, not a default value.
 */
 case OP_Column: {
   u32 payloadSize;   /* Number of bytes in the record */
@@ -2028,7 +2038,8 @@ case OP_Column: {
   /* Get the column information. If aOffset[p2] is non-zero, then 
   ** deserialize the value from the record. If aOffset[p2] is zero,
   ** then there are not enough fields in the record to satisfy the
-  ** request. The value is NULL in this case.
+  ** request.  In this case, set the value NULL or to P3 if P3 is
+  ** a pointer to a Mem object.
   */
   if( aOffset[p2] ){
     assert( rc==SQLITE_OK );
@@ -2045,7 +2056,7 @@ case OP_Column: {
     sqlite3VdbeSerialGet(zData, aType[p2], pTos);
     pTos->enc = db->enc;
   }else{
-    if( pOp->p3 ){
+    if( pOp->p3type==P3_MEM ){
       sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
     }else{
       pTos->flags = MEM_Null;
index 36e875f26eb3377974d1a0558f848ad678bc792c..7b1e5a7d3fbdbf87a05b6634b06c1cbccc666620 100644 (file)
 ** 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.149 2005/07/21 03:48:20 drh Exp $
+** $Id: where.c,v 1.150 2005/07/21 18:23:20 drh Exp $
 */
 #include "sqliteInt.h"
 
 /*
 ** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
 */
-#define BMS  (sizeof(Bitmask)*8-1)
+#define BMS  (sizeof(Bitmask)*8)
 
 /*
 ** Determine the number of elements in an array.
 */
 typedef struct WhereClause WhereClause;
 
-/*
-** An instance of the following structure holds information about how well
-** a particular index helps in a search.  A list of such structures is
-** attached to each SrcList_item of a SrcList.
-*/
-struct WhereIdx {
-  Index *pIdx;      /* The index under consideration */
-  Bitmask prereq;   /* Prerequesite FROM clause elements for using this index */
-  int nEqTerm;      /* Number of Idx column constrainted by == or IN */
-  int nTerm;        /* Total number of Index Columns used */
-  int flags;        /* Flags.  See below */
-  double rRowEst;   /* Estimated number of rows selected */
-  double rScore;    /* Score of this index */
-  WhereIdx *pNext;  /* Next WhereIdx on the same FROM clause element */
-};
-
 /*
 ** The query generator uses an array of instances of this structure to
 ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
@@ -900,6 +884,10 @@ static int nQPlan = 0;              /* Next free slow in _query_plan[] */
 **        end                        |-- by sqlite3WhereEnd()
 **      end                         /
 **
+** Note that the loops might not be nested in the order in which they
+** appear in the FROM clause if a different order is better able to make
+** use of indices.
+**
 ** There are Btree cursors associated with each table.  t1 uses cursor
 ** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.
 ** And so forth.  This routine generates code to open those VDBE cursors
@@ -972,20 +960,18 @@ WhereInfo *sqlite3WhereBegin(
   WhereClause wc;            /* The WHERE clause is divided into these terms */
   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 */
 
-  /* The number of terms in the FROM clause is limited by the number of
+  /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
   */
-  if( pTabList->nSrc>sizeof(Bitmask)*8 ){
-    sqlite3ErrorMsg(pParse, "at most %d tables in a join",
-       sizeof(Bitmask)*8);
+  if( pTabList->nSrc>BMS ){
+    sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
     return 0;
   }
 
   /* Split the WHERE clause into separate subexpressions where each
-  ** subexpression is separated by an AND operator.  If the wc.a[]
-  ** array fills up, the last entry might point to an expression which
-  ** contains additional unfactored AND operators.
+  ** subexpression is separated by an AND operator.
   */
   initMaskSet(&maskSet);
   whereClauseInit(&wc, pParse);
@@ -1012,7 +998,10 @@ WhereInfo *sqlite3WhereBegin(
     pWhere = 0;
   }
 
-  /* Analyze all of the subexpressions.
+  /* Analyze all of the subexpressions.  Note that exprAnalyze() might
+  ** add new virtual terms onto the end of the WHERE clause.  We do not
+  ** want to analyze these virtual terms, so start analyzing at the end
+  ** and work forward so that they added virtual terms are never processed.
   */
   for(i=0; i<pTabList->nSrc; i++){
     createMask(&maskSet, pTabList->a[i].iCursor);
@@ -1021,28 +1010,60 @@ WhereInfo *sqlite3WhereBegin(
     exprAnalyze(pTabList, &maskSet, &wc.a[i]);
   }
 
-  /* Chose the best index to use for each table in the FROM clause
+  /* Chose the best index to use for each table in the FROM clause.
+  **
+  ** This loop fills in the pWInfo->a[].pIdx and pWInfo->a[].flags fields
+  ** with information
+  ** Reorder tables if necessary in order to choose a good ordering.
+  ** However, LEFT JOIN tables cannot be reordered.
   */
   notReady = ~(Bitmask)0;
   pTabItem = pTabList->a;
   pLevel = pWInfo->a;
-  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
-    Index *pBest;
-    int flags;
-    bestIndex(pParse, &wc, pTabItem, notReady,
-              (i==0 && ppOrderBy) ? *ppOrderBy : 0,
-              &pBest, &flags);
-    if( flags & WHERE_ORDERBY ){
+  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 */
+    double score;               /* The score 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 */
+    double bestScore = -1.0;    /* The score of pBest */
+    int bestJ;                  /* The value of j */
+    Bitmask m;                  /* Bitmask value for j or bestJ */
+
+    for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
+      m = getMask(&maskSet, pTabItem->iCursor);
+      if( (m & notReady)==0 ){
+        if( j==iFrom ) iFrom++;
+        continue;
+      }
+      score = bestIndex(pParse, &wc, pTabItem, notReady,
+                        (j==0 && ppOrderBy) ? *ppOrderBy : 0,
+                        &pIdx, &flags);
+      if( score>bestScore ){
+        bestScore = score;
+        pBest = pIdx;
+        bestFlags = flags;
+        bestJ = j;
+      }
+      if( (pTabItem->jointype & JT_LEFT)!=0
+         || (j>0 && (pTabItem[-1].jointype & JT_LEFT)!=0)
+      ){
+        break;
+      }
+    }
+    if( bestFlags & WHERE_ORDERBY ){
       *ppOrderBy = 0;
     }
-    pLevel->flags = flags;
+    pLevel->flags = bestFlags;
     pLevel->pIdx = pBest;
     if( pBest ){
       pLevel->iIdxCur = pParse->nTab++;
     }else{
       pLevel->iIdxCur = -1;
     }
-    notReady &= ~getMask(&maskSet, pTabItem->iCursor);
+    notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);
+    pLevel->iFrom = bestJ;
   }
 
   /* Open all tables in the pTabList and any indices selected for
@@ -1050,11 +1071,12 @@ WhereInfo *sqlite3WhereBegin(
   */
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   pLevel = pWInfo->a;
-  for(i=0, pTabItem=pTabList->a; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
     Table *pTab;
     Index *pIx;
     int iIdxCur = pLevel->iIdxCur;
 
+    pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     if( pTab->isTransient || pTab->pSelect ) continue;
     if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
@@ -1063,6 +1085,7 @@ WhereInfo *sqlite3WhereBegin(
     pLevel->iTabCur = pTabItem->iCursor;
     if( (pIx = pLevel->pIdx)!=0 ){
       sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0);
+      VdbeComment((v, "# %s", pIx->zName));
       sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
                      (char*)&pIx->keyInfo, P3_KEYINFO);
     }
@@ -1070,80 +1093,43 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
     }
     sqlite3CodeVerifySchema(pParse, pTab->iDb);
-
-#ifdef SQLITE_TEST
-    /* Record in the query plan information about the current table
-    ** and the index used to access it (if any).  If the table itself
-    ** is not used, its name is just '{}'.  If no index is used
-    ** the index is listed as "{}"
-    */
-    {
-      char *z = pTabItem->zAlias;
-      int n;
-      if( z==0 ) z = pTab->zName;
-      n = strlen(z);
-      if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
-        if( pLevel->flags & WHERE_IDX_ONLY ){
-          strcpy(&sqlite3_query_plan[nQPlan], "{}");
-          nQPlan += 2;
-        }else{
-          strcpy(&sqlite3_query_plan[nQPlan], z);
-          nQPlan += n;
-        }
-        sqlite3_query_plan[nQPlan++] = ' ';
-      }
-      if( pIx==0 ){
-        strcpy(&sqlite3_query_plan[nQPlan], " {}");
-        nQPlan += 3;
-      }else{
-        n = strlen(pIx->zName);
-        if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
-          strcpy(&sqlite3_query_plan[nQPlan], pIx->zName);
-          nQPlan += n;
-          sqlite3_query_plan[nQPlan++] = ' ';
-        }
-      }
-    }
-#endif
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
 
-#ifdef SQLITE_TEST
-  /* Terminate the query plan description
-  */
-  while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
-    sqlite3_query_plan[--nQPlan] = 0;
-  }
-  sqlite3_query_plan[nQPlan] = 0;
-  nQPlan = 0;
-#endif
-
-  /* Generate the code to do the search
+  /* Generate the code to do the search.  Each iteration of the for
+  ** loop below generates code for a single nested loop of the VM
+  ** program.
   */
   notReady = ~(Bitmask)0;
-  pLevel = pWInfo->a;
-  pTabItem = pTabList->a;
-  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
     int j;
     int iCur = pTabItem->iCursor;  /* The VDBE cursor for the table */
     Index *pIdx;       /* The index we will be using */
     int iIdxCur;       /* The VDBE cursor for the index */
     int omitTable;     /* True if we use the index only */
+    int bRev;          /* True if we need to scan in reverse order */
 
+    pTabItem = &pTabList->a[pLevel->iFrom];
+    iCur = pTabItem->iCursor;
     pIdx = pLevel->pIdx;
     iIdxCur = pLevel->iIdxCur;
     pLevel->inOp = OP_Noop;
+    bRev = (pLevel->flags & WHERE_REVERSE)!=0;
+    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
 
-    /* Check to see if it is appropriate to omit the use of the table
-    ** here and use its index instead.
+    /* Create labels for the "break" and "continue" instructions
+    ** for the current loop.  Jump to brk to break out of a loop.
+    ** Jump to cont to go immediately to the next iteration of the
+    ** loop.
     */
-    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
+    brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
+    cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
 
     /* If this is the right table of a LEFT OUTER JOIN, allocate and
     ** initialize a memory cell that records if this table matches any
     ** row of the left table of the join.
     */
-    if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
+    if( pLevel->iFrom>0 && (pTabItem[-1].jointype & JT_LEFT)!=0 ){
       if( !pParse->nMem ) pParse->nMem++;
       pLevel->iLeftJoin = pParse->nMem++;
       sqlite3VdbeAddOp(v, OP_Null, 0, 0);
@@ -1162,9 +1148,7 @@ WhereInfo *sqlite3WhereBegin(
       assert( pTerm->pExpr!=0 );
       assert( pTerm->leftCursor==iCur );
       assert( omitTable==0 );
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
       codeEqualityTerm(pParse, pTerm, brk, pLevel);
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
       sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
       VdbeComment((v, "pk"));
@@ -1175,7 +1159,6 @@ WhereInfo *sqlite3WhereBegin(
       */
       int start;
       int nColumn;
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
 
       /* For each column of the index, find the term of the WHERE clause that
       ** constraints that column.  If the WHERE clause term is X=expr, then
@@ -1194,7 +1177,6 @@ WhereInfo *sqlite3WhereBegin(
       }
       nColumn = j;
       pLevel->iMem = pParse->nMem++;
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
       buildIndexProbe(v, nColumn, brk, pIdx);
       sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
 
@@ -1203,7 +1185,7 @@ WhereInfo *sqlite3WhereBegin(
       ** the last matching element of the table.  The code (1) is executed
       ** once to initialize the search, the code (2) is executed before each
       ** iteration of the scan to see if the scan has finished. */
-      if( pLevel->flags & WHERE_REVERSE ){
+      if( bRev ){
         /* Scan in reverse order */
         sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
         start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
@@ -1230,11 +1212,8 @@ WhereInfo *sqlite3WhereBegin(
       int testOp = OP_Noop;
       int start;
       WhereTerm *pStart, *pEnd;
-      int bRev = (pLevel->flags & WHERE_REVERSE)!=0;
 
       assert( omitTable==0 );
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
       if( pLevel->flags & WHERE_BTM_LIMIT ){
         pStart = findTerm(&wc, iCur, -1, notReady, WO_GT|WO_GE, 0);
         assert( pStart!=0 );
@@ -1308,7 +1287,6 @@ WhereInfo *sqlite3WhereBegin(
       int testOp;
       int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
       int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
-      int bRev = (pLevel->flags & WHERE_REVERSE)!=0;
 
       /* Evaluate the equality constraints
       */
@@ -1330,11 +1308,6 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeAddOp(v, OP_Dup, nEqColumn-1, 0);
       }
 
-      /* Labels for the beginning and end of the loop
-      */
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
-
       /* Generate the termination key.  This is the key value that
       ** will end the search.  There is no termination key if there
       ** are no equality terms and no "X<..." term.
@@ -1438,23 +1411,18 @@ WhereInfo *sqlite3WhereBegin(
       /* Case 5:  There is no usable index.  We must do a complete
       **          scan of the entire table.
       */
-      int start;
       int opRewind;
 
       assert( omitTable==0 );
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
-      if( pLevel->flags & WHERE_REVERSE ){
+      if( bRev ){
         opRewind = OP_Last;
         pLevel->op = OP_Prev;
       }else{
         opRewind = OP_Rewind;
         pLevel->op = OP_Next;
       }
-      sqlite3VdbeAddOp(v, opRewind, iCur, brk);
-      start = sqlite3VdbeCurrentAddr(v);
       pLevel->p1 = iCur;
-      pLevel->p2 = start;
+      pLevel->p2 = 1 + sqlite3VdbeAddOp(v, opRewind, iCur, brk);
     }
     notReady &= ~getMask(&maskSet, iCur);
 
@@ -1473,7 +1441,6 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3ExprIfFalse(pParse, pE, cont, 1);
       pTerm->flags |= TERM_CODED;
     }
-    brk = cont;
 
     /* For a LEFT OUTER JOIN, generate code that will record the fact that
     ** at least one row of the right table has matched the left table.  
@@ -1503,8 +1470,8 @@ WhereInfo *sqlite3WhereBegin(
   for(i=0; i<pTabList->nSrc; i++){
     char *z;
     int n;
-    pTabItem = &pTabList->a[i];
     pLevel = &pWInfo->a[i];
+    pTabItem = &pTabList->a[pLevel->iFrom];
     z = pTabItem->zAlias;
     if( z==0 ) z = pTabItem->pTab->zName;
     n = strlen(z);
@@ -1540,7 +1507,9 @@ WhereInfo *sqlite3WhereBegin(
   nQPlan = 0;
 #endif /* SQLITE_TEST // Testing and debugging use only */
 
-
+  /* Record the continuation address in the WhereInfo structure.  Then
+  ** clean up and return.
+  */
   pWInfo->iContinue = cont;
   freeMaskSet(&maskSet);
   whereClauseClear(&wc);
@@ -1556,7 +1525,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   int i;
   WhereLevel *pLevel;
   SrcList *pTabList = pWInfo->pTabList;
-  struct SrcList_item *pTabItem;
 
   /* Generate loop termination code.
   */
@@ -1587,11 +1555,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   */
   sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
 
-  /* Close all of the cursors that were opend by sqlite3WhereBegin.
+  /* Close all of the cursors that were opened by sqlite3WhereBegin.
   */
-  pLevel = pWInfo->a;
-  pTabItem = pTabList->a;
-  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
+    struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
     if( pTab->isTransient || pTab->pSelect ) continue;
@@ -1644,16 +1611,3 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   sqliteFree(pWInfo);
   return;
 }
-
-
-/*
-** Delete a list of WhereIdx structures.
-*/
-void sqlite3WhereIdxListDelete(WhereIdx *p){
-  WhereIdx *pNext;
-  while( p ){
-    pNext = p->pNext;
-    sqliteFree(p);
-    p = pNext;
-  }
-}