From: drh Date: Thu, 2 Jan 2020 00:45:38 +0000 (+0000) Subject: The sqlite3WhereEnd() call now unwinds all Expr modifications made by the X-Git-Tag: version-3.31.0~97 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=36e678bc398e864ec0806cf381408a57d6dcd4c4;p=thirdparty%2Fsqlite.git The sqlite3WhereEnd() call now unwinds all Expr modifications made by the sqlite3WhereBegin(). FossilOrigin-Name: 7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73 --- diff --git a/manifest b/manifest index db0f653441..1997e94b95 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index e2f996a6cd..10cbba2b95 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8ee2ce92c082771675d0e8be597043cf9f0fd4f8a73d6a1498bf8743d6b3904a \ No newline at end of file +7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index b441b9a4f7..1c03cf634e 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 ){ diff --git a/src/where.c b/src/where.c index 7c05a58e49..0877b80dd3 100644 --- a/src/where.c +++ b/src/where.c @@ -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; diff --git a/src/whereInt.h b/src/whereInt.h index f500e01d48..ad433652f4 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -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 */ diff --git a/src/wherecode.c b/src/wherecode.c index 96c2971a5f..beb23e0c18 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -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; iIdxColnColumn; iIdxCol++){ i16 iRef = pIdx->aiColumn[iIdxCol]; if( iRef==XN_EXPR ){