From: dan Date: Mon, 14 Jul 2014 19:04:29 +0000 (+0000) Subject: In the expression passed to sqlite3BtreeCursorHint() for the inner loops of joins... X-Git-Tag: version-3.10.0~191^2~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=159c1a18db659f3747111fb8ee83946710252867;p=thirdparty%2Fsqlite.git In the expression passed to sqlite3BtreeCursorHint() for the inner loops of joins, replace any TK_COLUMN references to columns in the outer loops with TK_REGISTER expressions (Expr.iTable indicates the specific register containing the value). FossilOrigin-Name: f9dddd008c6ef7940a1d66363fbb456cff7207c1 --- diff --git a/manifest b/manifest index 03b9a88b67..b8747caf6d 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 1397cacead..9676e57f7d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bfefc57554853e467ee6aeaba8d08331406fa216 \ No newline at end of file +f9dddd008c6ef7940a1d66363fbb456cff7207c1 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 9d6679a866..a218fd56c6 100644 --- a/src/where.c +++ b/src/where.c @@ -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; inTerm; 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; jnLTerm && pWLoop->aLTerm[j]!=pTerm; j++){} if( jnLTerm ) 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