From: drh Date: Thu, 21 Jul 2005 18:23:20 +0000 (+0000) Subject: Split the OP_Integer opcode into OP_Integer and OP_Int64. This allows X-Git-Tag: version-3.6.10~3603 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=29dda4ae6589366c709011925a7e71bc5e72f60d;p=thirdparty%2Fsqlite.git Split the OP_Integer opcode into OP_Integer and OP_Int64. This allows 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 --- diff --git a/manifest b/manifest index 684d41d12f..1bdabd6906 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index c2fac60364..0e108c626c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef3a157f469d72cbd2f713f997598ddf47f340d2 \ No newline at end of file +e2f822ac82d0a5a59de0b63cce65d4fd6c178ff1 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 3ad25d1d14..25b441454c 100644 --- a/src/build.c +++ b/src/build.c @@ -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 @@ -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); } diff --git a/src/delete.c b/src/delete.c index faf0f2fc81..8db7a8ad10 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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); } diff --git a/src/expr.c b/src/expr.c index 5f797029f4..6da0289b35 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.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 @@ -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); } diff --git a/src/insert.c b/src/insert.c index b236a10a26..428c8cd125 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.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); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3425008c51..1883a4dfb4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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<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)); + } } } diff --git a/src/vdbe.c b/src/vdbe.c index f6afbe027d..79292ec944 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.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; diff --git a/src/where.c b/src/where.c index 36e875f26e..7b1e5a7d3f 100644 --- a/src/where.c +++ b/src/where.c @@ -16,14 +16,14 @@ ** 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. @@ -34,22 +34,6 @@ */ 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; inSrc; 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; inSrc; 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; inSrc; 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]; jnSrc; 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; inSrc; i++, pTabItem++, pLevel++){ + for(i=0, pLevel=pWInfo->a; inSrc; 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; inSrc; i++, pTabItem++, pLevel++){ + for(i=0, pLevel=pWInfo->a; inSrc; 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; inSrc; 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; inSrc; i++, pTabItem++, pLevel++){ + for(i=0, pLevel=pWInfo->a; inSrc; 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; - } -}