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
This commit is contained in:
drh 2005-07-21 18:23:20 +00:00
parent 7ec764a29e
commit 29dda4ae65
10 changed files with 161 additions and 197 deletions

View File

@ -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

View File

@ -1 +1 @@
ef3a157f469d72cbd2f713f997598ddf47f340d2
e2f822ac82d0a5a59de0b63cce65d4fd6c178ff1

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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"

View 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));
}
}
}

View 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;

View File

@ -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; 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;
/* Check to see if it is appropriate to omit the use of the table
** here and use its index instead.
*/
bRev = (pLevel->flags & WHERE_REVERSE)!=0;
omitTable = (pLevel->flags & 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.
** Jump to cont to go immediately to the next iteration of the
** loop.
*/
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;
}
}