1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

The sqlite3WhereEnd() call now unwinds all Expr modifications made by the

sqlite3WhereBegin().

FossilOrigin-Name: 7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73
This commit is contained in:
drh
2020-01-02 00:45:38 +00:00
parent 2a83c10072
commit 36e678bc39
6 changed files with 63 additions and 28 deletions

View File

@@ -1,5 +1,5 @@
C Provide\sthe\s-DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1\scompile-time\soption.\s\sFix\nthe\s".testctrl\sinternal_function"\scommand\sin\sthe\sCLI\sso\sthat\sit\sdoes\snot\nsignal\san\serror\son\sa\svalid\sinput.
D 2020-01-01T23:02:35.846
C The\ssqlite3WhereEnd()\scall\snow\sunwinds\sall\sExpr\smodifications\smade\sby\sthe\nsqlite3WhereBegin().
D 2020-01-02T00:45:38.107
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -480,7 +480,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c 6c407e549406c10fde9ac3987f6d734459205239ad370369bc5fcd683084a4fa
F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4
F src/expr.c 7f3a19d0d400d079bd5e40389c75634a1b6feeb91eadfff5919d5b7d73f0c418
F src/expr.c e76660a57fa2bbe4103686dc8add1a8c5ca40ae139076956dc8c670f5af34e93
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847
F src/func.c 259496e4856bd0a3215d16804992f3339f3e8db29f129a5a7285c341488bbe9c
@@ -614,9 +614,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 15a2845769f51ba132f9cf0b2c7a6887a91fc8437892dbcce9fcdc68b66d60a1
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c a137468bf36c92e64d2275caa80c83902e3a0fc59273591b96c6416d3253d05d
F src/where.c 602e5093556bbd9090c0a9bd834fec0717e3a4b0377a021d38091a6d554a1177
F src/whereInt.h a727b32260e12707a8c1bc29d7f7e9b6dc1a44551a45093d5968fbe570ff0c56
F src/wherecode.c a987d22b42e09b06f3a49596e0953b1cd28e568cc656681776edc0026cfac0cc
F src/where.c 9353093c2a444580857006fc959494edc40e2393ac08a1f7e1eefe455c079cdb
F src/whereInt.h d2b771335083070ff82991cc43603e2db27b7ba1313da72de092c50c68f2be9c
F src/wherecode.c b8acf97f95de7398455e238036e96aeda8563d87c6b8108c967396431b6f2307
F src/whereexpr.c 4b34be1434183e7bb8a05d4bf42bd53ea53021b0b060936fbd12062b4ff6b396
F src/window.c 659d613248f8bb8630f51409dc08235e4494c3c84162a535d9f88b38515f390a
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1853,7 +1853,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 4edddcc0bc8d71e9b8abac67bc3766f1d9143dddd1f59264859ce65e5aa9b8c6
R 7719ca5b06b1882198898d45d0aa33b1
P 8ee2ce92c082771675d0e8be597043cf9f0fd4f8a73d6a1498bf8743d6b3904a
Q -4edddcc0bc8d71e9b8abac67bc3766f1d9143dddd1f59264859ce65e5aa9b8c6
R 78a3f85d954b3a0eb1fce93a6a40c0b8
U drh
Z a96bfaa62b0a101e6ed6e47d09a94ada
Z 7a9eae0197a9672b5fa1c50dd4bf6963

View File

@@ -1 +1 @@
8ee2ce92c082771675d0e8be597043cf9f0fd4f8a73d6a1498bf8743d6b3904a
7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73

View File

@@ -2933,8 +2933,6 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */
Expr *pLimit; /* New limit expression */
Select *pCopy; /* Copy of pSel */
int rc; /* return value from subroutine call */
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
@@ -3018,16 +3016,9 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0;
/* pSel might be reused. So generate code using a copy of pSel, so that
** if the code generator modifies the underlying structure of the SELECT
** (for example in whereIndexExprTrans()) the original in pSel will be
** unchanged. */
pCopy = sqlite3SelectDup(pParse->db, pSel, 0);
rc = sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
if( rc ) return 0;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){

View File

@@ -1942,6 +1942,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
assert( pWInfo->pExprMods==0 );
sqlite3DbFreeNN(db, pWInfo);
}
@@ -5440,6 +5441,14 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
/* Undo all Expr node modifications */
while( pWInfo->pExprMods ){
WhereExprMod *p = pWInfo->pExprMods;
pWInfo->pExprMods = p->pNext;
memcpy(p->pExpr, &p->orig, sizeof(p->orig));
sqlite3DbFree(db, p);
}
/* Final cleanup
*/
pParse->nQueryLoop = pWInfo->savedNQueryLoop;

View File

@@ -433,6 +433,20 @@ 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
@@ -449,24 +463,25 @@ struct WhereInfo {
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
Expr *pWhere; /* The complete WHERE clause */
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
u8 nLevel; /* Number of nested loop */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 sorted; /* True if really sorted (not just grouped) */
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
u8 bDeferredSeek; /* Uses OP_DeferredSeek */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
u8 bDeferredSeek : 1; /* Uses OP_DeferredSeek */
u8 untestedTerms : 1; /* Not all WHERE terms resolved by outer loop */
u8 bOrderedInnerLoop : 1; /* True if only the inner-most loop is ordered */
u8 sorted : 1; /* True if really sorted (not just grouped) */
LogEst nRowOut; /* Estimated number of output rows */
int iTop; /* The very beginning of the WHERE loop */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereExprMod *pExprMods; /* Expression modifications */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
LogEst nRowOut; /* Estimated number of output rows */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
WhereLevel a[1]; /* Information about each nest loop in WHERE */

View File

@@ -1113,8 +1113,23 @@ typedef struct IdxExprTrans {
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.
**
@@ -1124,6 +1139,7 @@ typedef struct IdxExprTrans {
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
@@ -1147,6 +1163,7 @@ static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
assert( pExpr->y.pTab!=0 );
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
@@ -1188,6 +1205,8 @@ static void whereIndexExprTrans(
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 ){