mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
The generalized indexed expression optimization of [2435112867fbd7b6] makes
the prior [a47efb7c8520a011] enhancement from 2017 obsolete. This check-in removes the older optimization. FossilOrigin-Name: 56442c9bdd7844454c79acf83323380ea3509cb2e0b9a3d538a6b51726ae6d07
This commit is contained in:
26
manifest
26
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\sminor\sproblems\sin\stest1.c\stest\scode.
|
||||
D 2022-10-20T10:46:17.479
|
||||
C The\sgeneralized\sindexed\sexpression\soptimization\sof\s[2435112867fbd7b6]\smakes\nthe\sprior\s[a47efb7c8520a011]\senhancement\sfrom\s2017\sobsolete.\s\sThis\scheck-in\nremoves\sthe\solder\soptimization.
|
||||
D 2022-10-20T13:36:32.870
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -570,7 +570,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
|
||||
F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec
|
||||
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
|
||||
F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e
|
||||
F src/expr.c 3ac1d9e87c018f804d10ab9ffa8bf55efef79c376e7ca90d21ac4ef67bfa8f25
|
||||
F src/expr.c 847f87d9df3ede2b2b0a8db088af0b9c1923b21009f8ea1b9b7b28cb0a383170
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
|
||||
F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a
|
||||
@@ -625,7 +625,7 @@ F src/shell.c.in 6a9e15cb9fc3cd13d3647d4d9714c0d4d4a65e7f49228c2aafca910ed08d577
|
||||
F src/sqlite.h.in d9c8a6243fc0a1c270d69db33758e34b810af3462f9bc5b4af113b347e07c69d
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 5336beea1868d99d2f62e628dbea55e97267dbff8193291ab175e960c5df9141
|
||||
F src/sqliteInt.h 872ab50cc285de11f7fdc0ce1f0481018f14905e4e0b75da43d8cba5a03b8d8d
|
||||
F src/sqliteInt.h f4f3ae8be17f3ef272d2e4a439df504706944b8fbd32b6fe76eefd1240d15a3a
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -702,15 +702,15 @@ F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
|
||||
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
|
||||
F src/vtab.c bb53f9e2eaeecca07158643dd3d5039cf13b525fe2d267e113b39a36f374556c
|
||||
F src/vtab.c b2f993aa954078985bc40317bb2140fe0880a08a7440f3a428b60fce74636808
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c 5dcd88d080ad302da4278f55acce12fd1c1f91eff2bcbfa2c0806d33fa230a5f
|
||||
F src/whereInt.h 89a0ae1af68264c925f9729c247ae01457b3d2400b8f0626345e2a15bb30d7b8
|
||||
F src/wherecode.c 8ec5a413f12af06638dcca36d0954be2151eea6f293d3c67397cef6a90d6adf1
|
||||
F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405
|
||||
F src/where.c 4c5f6a6f3c7a2fe110380b52edd27628074ae0b66c7f62e2fba47897098828aa
|
||||
F src/whereInt.h e5f5cf1bc32b7d01a6337027478ef6ed90c8c403de4b977198345c8238f0e1b0
|
||||
F src/wherecode.c 13b6373af69d484d9b05b9a732d393ce3b7b320cc93275c6528127678650f8cb
|
||||
F src/whereexpr.c a1bd9d8faddc946d19ae8b6b3468874794bf54acd13fe46e1680fb428e8d3ea7
|
||||
F src/window.c 928e215840e2f2d9a2746e018c9643ef42c66c4ab6630ef0df7fa388fa145e86
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
@@ -2036,8 +2036,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P cdd46858f0e63bc7bfce8e339b3db9efdec43b6443ee76563a847f53d0176831
|
||||
R ce083a526f8539552e7d3cfc7a645ff7
|
||||
U dan
|
||||
Z 0e03056726a19a84c80763f2bed74dfa
|
||||
P 6e545e2b846795fc67f8a90c04de284861a8a429ac686a7476b41c8ed7aabf75
|
||||
R 228ae945140472bb5e1b236e96f4ecd2
|
||||
U drh
|
||||
Z dcc82e93e2bb9bb5c1a3735a5f91159f
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@@ -1 +1 @@
|
||||
6e545e2b846795fc67f8a90c04de284861a8a429ac686a7476b41c8ed7aabf75
|
||||
56442c9bdd7844454c79acf83323380ea3509cb2e0b9a3d538a6b51726ae6d07
|
40
src/expr.c
40
src/expr.c
@@ -55,9 +55,8 @@ char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
if( op==TK_REGISTER ) op = pExpr->op2;
|
||||
if( op==TK_COLUMN || op==TK_AGG_COLUMN ){
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
if( pExpr->y.pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
}
|
||||
assert( pExpr->y.pTab!=0 );
|
||||
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
}
|
||||
if( op==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
@@ -175,17 +174,14 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
int op = p->op;
|
||||
if( op==TK_REGISTER ) op = p->op2;
|
||||
if( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER ){
|
||||
int j;
|
||||
assert( ExprUseYTab(p) );
|
||||
if( p->y.pTab!=0 ){
|
||||
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
|
||||
** a TK_COLUMN but was previously evaluated and cached in a register */
|
||||
int j = p->iColumn;
|
||||
if( j>=0 ){
|
||||
const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
|
||||
}
|
||||
break;
|
||||
assert( p->y.pTab!=0 );
|
||||
if( (j = p->iColumn)>=0 ){
|
||||
const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( op==TK_CAST || op==TK_UPLUS ){
|
||||
p = p->pLeft;
|
||||
@@ -3790,10 +3786,7 @@ void sqlite3ExprCodeGetColumnOfTable(
|
||||
){
|
||||
Column *pCol;
|
||||
assert( v!=0 );
|
||||
if( pTab==0 ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
|
||||
return;
|
||||
}
|
||||
assert( pTab!=0 );
|
||||
if( iCol<0 || iCol==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
|
||||
VdbeComment((v, "%s.rowid", pTab->zName));
|
||||
@@ -4168,11 +4161,8 @@ expr_code_doover:
|
||||
int aff;
|
||||
iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
if( pExpr->y.pTab ){
|
||||
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
}else{
|
||||
aff = pExpr->affExpr;
|
||||
}
|
||||
assert( pExpr->y.pTab!=0 );
|
||||
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
if( aff>SQLITE_AFF_BLOB ){
|
||||
static const char zAff[] = "B\000C\000D\000E";
|
||||
assert( SQLITE_AFF_BLOB=='A' );
|
||||
@@ -4234,12 +4224,10 @@ expr_code_doover:
|
||||
}
|
||||
}
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
assert( pExpr->y.pTab!=0 );
|
||||
iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
|
||||
pExpr->iColumn, iTab, target,
|
||||
pExpr->op2);
|
||||
if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
|
||||
}
|
||||
return iReg;
|
||||
}
|
||||
case TK_INTEGER: {
|
||||
@@ -5930,10 +5918,10 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
||||
assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
|
||||
assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
|
||||
if( (pLeft->op==TK_COLUMN
|
||||
&& pLeft->y.pTab!=0
|
||||
&& ALWAYS(pLeft->y.pTab!=0)
|
||||
&& IsVirtual(pLeft->y.pTab))
|
||||
|| (pRight->op==TK_COLUMN
|
||||
&& pRight->y.pTab!=0
|
||||
&& ALWAYS(pRight->y.pTab!=0)
|
||||
&& IsVirtual(pRight->y.pTab))
|
||||
){
|
||||
return WRC_Prune;
|
||||
|
@@ -2361,7 +2361,7 @@ struct Table {
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
|
||||
# define ExprIsVtab(X) \
|
||||
((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
|
||||
((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB)
|
||||
#else
|
||||
# define IsVirtual(X) 0
|
||||
# define ExprIsVtab(X) 0
|
||||
|
@@ -1141,7 +1141,7 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
if( pExpr->op!=TK_COLUMN ) return pDef;
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
pTab = pExpr->y.pTab;
|
||||
if( pTab==0 ) return pDef;
|
||||
if( NEVER(pTab==0) ) return pDef;
|
||||
if( !IsVirtual(pTab) ) return pDef;
|
||||
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
|
17
src/where.c
17
src/where.c
@@ -2287,7 +2287,6 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
pWInfo->pLoops = p->pNextLoop;
|
||||
whereLoopDelete(db, p);
|
||||
}
|
||||
assert( pWInfo->pExprMods==0 );
|
||||
while( pWInfo->pMemToFree ){
|
||||
WhereMemBlock *pNext = pWInfo->pMemToFree->pNext;
|
||||
sqlite3DbNNFreeNN(db, pWInfo->pMemToFree);
|
||||
@@ -2296,17 +2295,6 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
sqlite3DbNNFreeNN(db, pWInfo);
|
||||
}
|
||||
|
||||
/* Undo all Expr node modifications
|
||||
*/
|
||||
static void whereUndoExprMods(WhereInfo *pWInfo){
|
||||
while( pWInfo->pExprMods ){
|
||||
WhereExprMod *p = pWInfo->pExprMods;
|
||||
pWInfo->pExprMods = p->pNext;
|
||||
memcpy(p->pExpr, &p->orig, sizeof(p->orig));
|
||||
sqlite3DbFree(pWInfo->pParse->db, p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if all of the following are true:
|
||||
**
|
||||
@@ -5608,7 +5596,9 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
#if WHERETRACE_ENABLED
|
||||
pWInfo->pWhere = pWhere;
|
||||
#endif
|
||||
pWInfo->pResultSet = pResultSet;
|
||||
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
|
||||
pWInfo->nLevel = nTabList;
|
||||
@@ -6115,8 +6105,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
/* Jump here if malloc fails */
|
||||
whereBeginError:
|
||||
if( pWInfo ){
|
||||
testcase( pWInfo->pExprMods!=0 );
|
||||
whereUndoExprMods(pWInfo);
|
||||
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
|
||||
whereInfoFree(db, pWInfo);
|
||||
}
|
||||
@@ -6335,7 +6323,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}
|
||||
|
||||
assert( pWInfo->nLevel<=pTabList->nSrc );
|
||||
if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
|
||||
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
|
||||
int k, last;
|
||||
VdbeOp *pOp, *pLastOp;
|
||||
|
@@ -449,20 +449,6 @@ struct WhereLoopBuilder {
|
||||
# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Each instance of this object records a change to a single node
|
||||
** in an expression tree to cause that node to point to a column
|
||||
** of an index rather than an expression or a virtual column. All
|
||||
** such transformations need to be undone at the end of WHERE clause
|
||||
** processing.
|
||||
*/
|
||||
typedef struct WhereExprMod WhereExprMod;
|
||||
struct WhereExprMod {
|
||||
WhereExprMod *pNext; /* Next translation on a list of them all */
|
||||
Expr *pExpr; /* The Expr node that was transformed */
|
||||
Expr orig; /* Original value of the Expr node */
|
||||
};
|
||||
|
||||
/*
|
||||
** The WHERE clause processing routine has two halves. The
|
||||
** first part does the start of the WHERE loop and the second
|
||||
@@ -478,7 +464,9 @@ struct WhereInfo {
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pResultSet; /* Result set of the query */
|
||||
#if WHERETRACE_ENABLED
|
||||
Expr *pWhere; /* The complete WHERE clause */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */
|
||||
#endif
|
||||
@@ -500,7 +488,6 @@ struct WhereInfo {
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iEndWhere; /* End of the WHERE clause itself */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
WhereExprMod *pExprMods; /* Expression modifications */
|
||||
WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
WhereClause sWC; /* Decomposition of the WHERE clause */
|
||||
|
158
src/wherecode.c
158
src/wherecode.c
@@ -1217,143 +1217,6 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
|
||||
}
|
||||
}
|
||||
|
||||
/* An instance of the IdxExprTrans object carries information about a
|
||||
** mapping from an expression on table columns into a column in an index
|
||||
** down through the Walker.
|
||||
*/
|
||||
typedef struct IdxExprTrans {
|
||||
Expr *pIdxExpr; /* The index expression */
|
||||
int iTabCur; /* The cursor of the corresponding table */
|
||||
int iIdxCur; /* The cursor for the index */
|
||||
int iIdxCol; /* The column for the index */
|
||||
int iTabCol; /* The column for the table */
|
||||
WhereInfo *pWInfo; /* Complete WHERE clause information */
|
||||
sqlite3 *db; /* Database connection (for malloc()) */
|
||||
} IdxExprTrans;
|
||||
|
||||
/*
|
||||
** Preserve pExpr on the WhereETrans list of the WhereInfo.
|
||||
*/
|
||||
static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
|
||||
WhereExprMod *pNew;
|
||||
pNew = sqlite3DbMallocRaw(pTrans->db, sizeof(*pNew));
|
||||
if( pNew==0 ) return;
|
||||
pNew->pNext = pTrans->pWInfo->pExprMods;
|
||||
pTrans->pWInfo->pExprMods = pNew;
|
||||
pNew->pExpr = pExpr;
|
||||
memcpy(&pNew->orig, pExpr, sizeof(*pExpr));
|
||||
}
|
||||
|
||||
/* The walker node callback used to transform matching expressions into
|
||||
** a reference to an index column for an index on an expression.
|
||||
**
|
||||
** If pExpr matches, then transform it into a reference to the index column
|
||||
** that contains the value of pExpr.
|
||||
*/
|
||||
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
||||
IdxExprTrans *pX = p->u.pIdxTrans;
|
||||
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
|
||||
pExpr = sqlite3ExprSkipCollate(pExpr);
|
||||
preserveExpr(pX, pExpr);
|
||||
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
|
||||
pExpr->op = TK_COLUMN;
|
||||
pExpr->iTable = pX->iIdxCur;
|
||||
pExpr->iColumn = pX->iIdxCol;
|
||||
testcase( ExprHasProperty(pExpr, EP_Unlikely) );
|
||||
ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn);
|
||||
pExpr->y.pTab = 0;
|
||||
return WRC_Prune;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
/* A walker node callback that translates a column reference to a table
|
||||
** into a corresponding column reference of an index.
|
||||
*/
|
||||
static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
|
||||
if( pExpr->op==TK_COLUMN ){
|
||||
IdxExprTrans *pX = p->u.pIdxTrans;
|
||||
if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
|
||||
assert( ExprUseYTab(pExpr) && pExpr->y.pTab!=0 );
|
||||
preserveExpr(pX, pExpr);
|
||||
pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
|
||||
pExpr->iTable = pX->iIdxCur;
|
||||
pExpr->iColumn = pX->iIdxCol;
|
||||
pExpr->y.pTab = 0;
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
||||
|
||||
/*
|
||||
** For an indexes on expression X, locate every instance of expression X
|
||||
** in pExpr and change that subexpression into a reference to the appropriate
|
||||
** column of the index.
|
||||
**
|
||||
** 2019-10-24: Updated to also translate references to a VIRTUAL column in
|
||||
** the table into references to the corresponding (stored) column of the
|
||||
** index.
|
||||
*/
|
||||
static void whereIndexExprTrans(
|
||||
Index *pIdx, /* The Index */
|
||||
int iTabCur, /* Cursor of the table that is being indexed */
|
||||
int iIdxCur, /* Cursor of the index itself */
|
||||
WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
|
||||
){
|
||||
int iIdxCol; /* Column number of the index */
|
||||
ExprList *aColExpr; /* Expressions that are indexed */
|
||||
Table *pTab;
|
||||
Walker w;
|
||||
IdxExprTrans x;
|
||||
aColExpr = pIdx->aColExpr;
|
||||
if( aColExpr==0 && !pIdx->bHasVCol ){
|
||||
/* The index does not reference any expressions or virtual columns
|
||||
** so no translations are needed. */
|
||||
return;
|
||||
}
|
||||
pTab = pIdx->pTable;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.u.pIdxTrans = &x;
|
||||
x.iTabCur = iTabCur;
|
||||
x.iIdxCur = iIdxCur;
|
||||
x.pWInfo = pWInfo;
|
||||
x.db = pWInfo->pParse->db;
|
||||
for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
|
||||
i16 iRef = pIdx->aiColumn[iIdxCol];
|
||||
if( iRef==XN_EXPR ){
|
||||
assert( aColExpr!=0 && aColExpr->a[iIdxCol].pExpr!=0 );
|
||||
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
|
||||
if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
|
||||
w.xExprCallback = whereIndexExprTransNode;
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
}else if( iRef>=0
|
||||
&& (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
|
||||
&& ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
|
||||
|| sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]),
|
||||
sqlite3StrBINARY)==0)
|
||||
){
|
||||
/* Check to see if there are direct references to generated columns
|
||||
** that are contained in the index. Pulling the generated column
|
||||
** out of the index is an optimization only - the main table is always
|
||||
** available if the index cannot be used. To avoid unnecessary
|
||||
** complication, omit this optimization if the collating sequence for
|
||||
** the column is non-standard */
|
||||
x.iTabCol = iRef;
|
||||
w.xExprCallback = whereIndexExprTransColumn;
|
||||
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
x.iIdxCol = iIdxCol;
|
||||
sqlite3WalkExpr(&w, pWInfo->pWhere);
|
||||
sqlite3WalkExprList(&w, pWInfo->pOrderBy);
|
||||
sqlite3WalkExprList(&w, pWInfo->pResultSet);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The pTruth expression is always true because it is the WHERE clause
|
||||
** a partial index that is driving a query loop. Look through all of the
|
||||
@@ -2181,27 +2044,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
|
||||
if( pLevel->iLeftJoin==0 ){
|
||||
/* If pIdx is an index on one or more expressions, then look through
|
||||
** all the expressions in pWInfo and try to transform matching expressions
|
||||
** into reference to index columns. Also attempt to translate references
|
||||
** to virtual columns in the table into references to (stored) columns
|
||||
** of the index.
|
||||
**
|
||||
** Do not do this for the RHS of a LEFT JOIN. This is because the
|
||||
** expression may be evaluated after OP_NullRow has been executed on
|
||||
** the cursor. In this case it is important to do the full evaluation,
|
||||
** as the result of the expression may not be NULL, even if all table
|
||||
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
|
||||
**
|
||||
** Also, do not do this when processing one index an a multi-index
|
||||
** OR clause, since the transformation will become invalid once we
|
||||
** move forward to the next index.
|
||||
** https://sqlite.org/src/info/4e8e4857d32d401f
|
||||
*/
|
||||
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ){
|
||||
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
||||
}
|
||||
|
||||
/* If a partial index is driving the loop, try to eliminate WHERE clause
|
||||
** terms from the query that must be true due to the WHERE clause of
|
||||
** the partial index.
|
||||
|
@@ -266,7 +266,7 @@ static int isLikeOrGlob(
|
||||
if( pLeft->op!=TK_COLUMN
|
||||
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
||||
|| (ALWAYS( ExprUseYTab(pLeft) )
|
||||
&& pLeft->y.pTab
|
||||
&& ALWAYS(pLeft->y.pTab)
|
||||
&& IsVirtual(pLeft->y.pTab)) /* Might be numeric */
|
||||
){
|
||||
int isNum;
|
||||
@@ -383,8 +383,7 @@ static int isAuxiliaryVtabOperator(
|
||||
** MATCH(expression,vtab_column)
|
||||
*/
|
||||
pCol = pList->a[1].pExpr;
|
||||
assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
|
||||
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
||||
assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
|
||||
if( ExprIsVtab(pCol) ){
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
@@ -409,7 +408,7 @@ static int isAuxiliaryVtabOperator(
|
||||
*/
|
||||
pCol = pList->a[0].pExpr;
|
||||
assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
|
||||
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
||||
assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
|
||||
if( ExprIsVtab(pCol) ){
|
||||
sqlite3_vtab *pVtab;
|
||||
sqlite3_module *pMod;
|
||||
@@ -434,13 +433,12 @@ static int isAuxiliaryVtabOperator(
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
|
||||
testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
|
||||
assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
|
||||
if( ExprIsVtab(pLeft) ){
|
||||
res++;
|
||||
}
|
||||
assert( pRight==0 || pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
|
||||
testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
|
||||
assert( pRight==0 || pRight->op!=TK_COLUMN
|
||||
|| (ExprUseYTab(pRight) && pRight->y.pTab!=0) );
|
||||
if( pRight && ExprIsVtab(pRight) ){
|
||||
res++;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
|
Reference in New Issue
Block a user