]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
In the expression passed to sqlite3BtreeCursorHint() for the inner loops of joins...
authordan <dan@noemail.net>
Mon, 14 Jul 2014 19:04:29 +0000 (19:04 +0000)
committerdan <dan@noemail.net>
Mon, 14 Jul 2014 19:04:29 +0000 (19:04 +0000)
FossilOrigin-Name: f9dddd008c6ef7940a1d66363fbb456cff7207c1

manifest
manifest.uuid
src/where.c

index 03b9a88b677d3b893c0908868272e9c9b0bd836a..b8747caf6dacaca1bfce20f627255f0345405ce9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sallow\scursor\shints\sto\suse\sexpressions\scontaining\ssubqueries.\s\sThis\nchange\sfixes\sthe\sproblem\sseen\sin\sthe\sprevious\scheck-in.
-D 2013-12-07T23:35:21.843
+C In\sthe\sexpression\spassed\sto\ssqlite3BtreeCursorHint()\sfor\sthe\sinner\sloops\sof\sjoins,\sreplace\sany\sTK_COLUMN\sreferences\sto\scolumns\sin\sthe\souter\sloops\swith\sTK_REGISTER\sexpressions\s(Expr.iTable\sindicates\sthe\sspecific\sregister\scontaining\sthe\svalue).
+D 2014-07-14T19:04:29.385
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in e1a9b4258bbde53f5636f4e238c65b7e11459e2b
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -293,7 +293,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
 F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
-F src/where.c 34cf76979535b933b39403f81c8c757cf3c4fe9f
+F src/where.c dcea6104452e837cc63bd1c3c5cb05868bb356ba
 F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1146,7 +1146,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 3a9bec524ef2de44028b4058e67dc962082888d3
-R e725a27255f076e1cf88ead0905058a7
-U drh
-Z 572bab5aee8e2ee9e755c685fab22b9b
+P bfefc57554853e467ee6aeaba8d08331406fa216
+R d30e9be65b11497e93ad990065d669d6
+U dan
+Z c72f8637bcd1205d8e636acedbe3ca98
index 1397cacead042d48d0217d93bd9c66aa279d416b..9676e57f7d18b2c997125a01f9d1a3948fb1533c 100644 (file)
@@ -1 +1 @@
-bfefc57554853e467ee6aeaba8d08331406fa216
\ No newline at end of file
+f9dddd008c6ef7940a1d66363fbb456cff7207c1
\ No newline at end of file
index 9d6679a8666641e2515dc7e9edb3250e805bf261..a218fd56c608328a4a455ab4eabaff41a12a50e9 100644 (file)
@@ -2716,6 +2716,41 @@ static void explainOneScan(
 #endif /* SQLITE_OMIT_EXPLAIN */
 
 #ifdef SQLITE_ENABLE_CURSOR_HINTS
+
+/*
+** This function is called on every node of an expression tree used as an
+** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN
+** that accesses any cursor other than (pWalker->u.i), do the following:
+**
+**   1) allocate a register and code an OP_Column instruction to read 
+**      the specified column into the new register, and
+**
+**   2) transform the expression node to a TK_REGISTER node that reads 
+**      from the newly populated register.
+*/
+static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
+  int rc = WRC_Continue;
+  if( pExpr->op==TK_COLUMN && pExpr->iTable!=pWalker->u.i ){
+    Vdbe *v = pWalker->pParse->pVdbe;
+    int reg = ++pWalker->pParse->nMem;   /* Register for column value */
+    sqlite3ExprCodeGetColumnOfTable(
+        v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg
+    );
+    pExpr->op = TK_REGISTER;
+    pExpr->iTable = reg;
+  }else if( pExpr->op==TK_AGG_FUNCTION ){
+    /* An aggregate function in the WHERE clause of a query means this must
+    ** be a correlated sub-query, and expression pExpr is an aggregate from
+    ** the parent context. Do not walk the function arguments in this case.
+    **
+    ** todo: It should be possible to replace this node with a TK_REGISTER
+    ** expression, as the result of the expression must be stored in a 
+    ** register at this point. The same holds for TK_AGG_COLUMN nodes. */
+    rc = WRC_Prune;
+  }
+  return rc;
+}
+
 /*
 ** Insert an OP_CursorHint instruction if it is appropriate to do so.
 */
@@ -2739,20 +2774,26 @@ static void codeCursorHint(
   pLevel = &pWInfo->a[iLevel];
   pWLoop = pLevel->pWLoop;
   iCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
-  msk = ~getMask(&pWInfo->sMaskSet, iCur);
   pWC = &pWInfo->sWC;
   for(i=0; i<pWC->nTerm; i++){
     pTerm = &pWC->a[i];
-    if( pTerm->prereqAll & msk ) continue;
+    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+    if( pTerm->prereqAll & pLevel->notReady ) continue;
     if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
     if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue;
     for(j=0; j<pWLoop->nLTerm && pWLoop->aLTerm[j]!=pTerm; j++){}
     if( j<pWLoop->nLTerm ) continue;
     pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
-  } 
+  }
   if( pExpr!=0 ){
-    sqlite3VdbeAddOp4(v, OP_CursorHint, pLevel->iTabCur, iCur, 0,
-                      (const char*)pExpr, P4_EXPR);
+    const char *a = (const char*)pExpr;
+    Walker sWalker;
+    memset(&sWalker, 0, sizeof(sWalker));
+    sWalker.xExprCallback = codeCursorHintFixExpr;
+    sWalker.pParse = pParse;
+    sWalker.u.i = pLevel->iTabCur;
+    sqlite3WalkExpr(&sWalker, pExpr);
+    sqlite3VdbeAddOp4(v, OP_CursorHint, pLevel->iTabCur, iCur, 0, a, P4_EXPR);
   }
 }
 #else