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:
parent
7ec764a29e
commit
29dda4ae65
26
manifest
26
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
|
||||
|
@ -1 +1 @@
|
||||
ef3a157f469d72cbd2f713f997598ddf47f340d2
|
||||
e2f822ac82d0a5a59de0b63cce65d4fd6c178ff1
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
53
src/vdbe.c
53
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;
|
||||
|
220
src/where.c
220
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; 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user