]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The sqlite3WhereEnd() call now unwinds all Expr modifications made by the
authordrh <drh@noemail.net>
Thu, 2 Jan 2020 00:45:38 +0000 (00:45 +0000)
committerdrh <drh@noemail.net>
Thu, 2 Jan 2020 00:45:38 +0000 (00:45 +0000)
sqlite3WhereBegin().

FossilOrigin-Name: 7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73

manifest
manifest.uuid
src/expr.c
src/where.c
src/whereInt.h
src/wherecode.c

index db0f6534410b4255c12e059be19d851af6677cc3..1997e94b958773b3df8b5ab7391d4fa33571582e 100644 (file)
--- 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
index e2f996a6cd2c13e491ff70214c81a22faa30ae11..10cbba2b95643288426a79c9120e178d073e917d 100644 (file)
@@ -1 +1 @@
-8ee2ce92c082771675d0e8be597043cf9f0fd4f8a73d6a1498bf8743d6b3904a
\ No newline at end of file
+7bfd42f1dc0c94f9bb74516e62fec8e39c20f4749f4e0972f66c2886d3c64f73
\ No newline at end of file
index b441b9a4f7f52adf47cecedef8d57eaff5683e36..1c03cf634e39ef08a69750108342a649806a2c59 100644 (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 ){
index 7c05a58e497c4ab2a7a22983307b038c68ab1369..0877b80dd35d13d9c53a5e0408cc63f68df340d9 100644 (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;
index f500e01d48390beec375a5b1c91d6494d278a23b..ad433652f48b4cc6ff61ed60b89fa9b447c4fb56 100644 (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 */
index 96c2971a5f58ad01dee42e91457b63b477affbd4..beb23e0c189a535d0d0c18b4f7da739cbad6f726 100644 (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 ){