From: drh Date: Tue, 7 May 2013 23:06:23 +0000 (+0000) Subject: Continued progress on generating good WhereLoop objects for the new query X-Git-Tag: version-3.8.0~130^2~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43fe25fcef6f0fa329c2a9748bc3794d783e12b9;p=thirdparty%2Fsqlite.git Continued progress on generating good WhereLoop objects for the new query planner. FossilOrigin-Name: 15cc8a16482777d8e138c4d0863faf8d54fef33a --- diff --git a/manifest b/manifest index 29d28aecb0..c79d6f38fd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Inserting\sa\sfew\sWhereLoop\sobjects\swithout\sleaking\smemory.\s\sCosts\sare\nnot\scorrect.\s\sInequality\sand\sIN\sconstraints\sare\snot\simplemented. -D 2013-05-07T19:44:38.531 +C Continued\sprogress\son\sgenerating\sgood\sWhereLoop\sobjects\sfor\sthe\snew\squery\nplanner. +D 2013-05-07T23:06:23.630 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -263,7 +263,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d F src/wal.h a4d3da523d55a226a0b28e9058ef88d0a8051887 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c e987a4ff2818b812f902361c1131fef4a8f95a41 +F src/where.c e957c2c6fd7b421ea6dd1ff11d254c80d0b11638 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1060,7 +1060,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P dd92b8fa929badaf2f79e8a00c83667a9d589096 -R 20c9cc42b7ec6059ab1cb985542962e1 +P e8881a8b2f25f38bc8ff77619f96f38fe530d13b +R 90f142cd2d5094cb6ddc049cebfe5b6d U drh -Z 6dee1758f1f268139b7d8139f9ade772 +Z d9519f5b83b11415ad77247122aa0d25 diff --git a/manifest.uuid b/manifest.uuid index 62ed5b5e8a..82bc167f3b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e8881a8b2f25f38bc8ff77619f96f38fe530d13b \ No newline at end of file +15cc8a16482777d8e138c4d0863faf8d54fef33a \ No newline at end of file diff --git a/src/where.c b/src/where.c index 4776a2b231..56568989aa 100644 --- a/src/where.c +++ b/src/where.c @@ -315,6 +315,7 @@ struct WhereLoopBuilder { */ #define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */ #define WHERE_ROWID_RANGE 0x00002000 /* rowidEXPR */ +#define WHERE_IPK 0x00004000 /* x is the INTEGER PRIMARY KEY */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* xEXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ @@ -710,6 +711,15 @@ WhereTerm *whereScanNext(WhereScan *pScan){ iColumn = pScan->aEquiv[pScan->iEquiv-1]; while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+pScan->k; pScan->knTerm; pScan->k++, pTerm++){ + if( pTerm->iParent>=0 ){ + WhereTerm *pParent = &pWC->a[pTerm->iParent]; + int j; + for(j=pScan->iEquiv-4; j>=0; j-=2 ){ + if( pParent->leftCursor==pScan->aEquiv[j] + && pParent->u.leftColumn==pScan->aEquiv[j+1] ) break; + } + if( j>=0 ) continue; + } if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaEquiv) @@ -5091,7 +5101,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** added based no the template. */ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ - WhereLoop **ppPrev, *p; + WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0; sqlite3 *db = pWInfo->pParse->db; /* Search for an existing WhereLoop to overwrite, or which takes @@ -5117,7 +5127,7 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ ){ /* Overwrite an existing WhereLoop with a better one */ sqlite3DbFree(db, p->aTerm); - *ppPrev = p->pNextLoop; + pNext = p->pNextLoop; break; } } @@ -5127,18 +5137,19 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ ** WhereLoop and insert it. */ if( p==0 ){ - p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); + p = pToFree = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); if( p==0 ) return SQLITE_NOMEM; } *p = *pTemplate; - p->pNextLoop = pWInfo->pLoops; - pWInfo->pLoops = p; - if( pTemplate->nTerm<=0 ) return SQLITE_OK; + p->pNextLoop = pNext; + *ppPrev = p; + p->aTerm = 0; if( p->pIndex && p->pIndex->tnum==0 ) p->pIndex = 0; + if( pTemplate->nTerm<=0 ) return SQLITE_OK; p->aTerm = sqlite3DbMallocRaw(db, pTemplate->nTerm*sizeof(p->aTerm[0])); if( p->aTerm==0 ){ p->nTerm = 0; - sqlite3DbFree(db, p); + sqlite3DbFree(db, pToFree); return SQLITE_NOMEM; } memcpy(p->aTerm, pTemplate->aTerm, pTemplate->nTerm*sizeof(p->aTerm[0])); @@ -5154,6 +5165,7 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ */ static void whereLoopAddBtreeIndex( WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ + Bitmask maskSelf, /* Bitmask for table being scanned */ struct SrcList_item *pSrc, /* FROM clause term being analyzed */ Index *pProbe, /* An index on pSrc */ int nInMul /* Number of iterations due to IN */ @@ -5161,18 +5173,22 @@ static void whereLoopAddBtreeIndex( sqlite3 *db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ - int eqTermMask; /* Valid equality operators */ + int opMask; /* Valid operators for constraints */ WhereScan scan; /* Iterator for WHERE terms */ - WhereLoop savedLoop; + WhereLoop savedLoop; /* Saved original content of pNew[] */ db = pBuilder->db; pNew = pBuilder->pNew; if( db->mallocFailed ) return; - if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ - eqTermMask = WO_EQ|WO_IN; + assert( pNew->nEqnColumn ); + assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); + if( pNew->wsFlags & WHERE_BTM_LIMIT ){ + opMask = WO_LT|WO_LE; + }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ + opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; }else{ - eqTermMask = WO_EQ|WO_IN|WO_ISNULL; + opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; } @@ -5182,24 +5198,42 @@ static void whereLoopAddBtreeIndex( iCol = pProbe->aiColumn[pNew->nEq]; pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, - eqTermMask, iCol>=0 ? pProbe : 0); + opMask, iCol>=0 ? pProbe : 0); savedLoop = *pNew; - pNew->nEq++; - pNew->nTerm++; + pNew->rSetup = (double)0; for(; pTerm!=0; pTerm = whereScanNext(&scan)){ - pNew->aTerm[pNew->nEq-1] = pTerm; - pNew->nOut = (double)(pProbe->aiRowEst[pNew->nEq] * nInMul); - pNew->rSetup = (double)0; - pNew->rRun = pNew->nOut; - pNew->prereq = savedLoop.prereq | pTerm->prereqRight; - if( pProbe->tnum<=0 ){ - pNew->wsFlags = savedLoop.wsFlags | WHERE_ROWID_EQ; - }else{ - pNew->wsFlags = savedLoop.wsFlags | WHERE_COLUMN_EQ; + int nIn = 1; + pNew->nEq = savedLoop.nEq; + pNew->nTerm = savedLoop.nTerm; + pNew->aTerm[pNew->nTerm++] = pTerm; + pNew->prereq = (savedLoop.prereq | pTerm->prereqRight) & ~maskSelf; + if( pTerm->eOperator & WO_IN ){ + Expr *pExpr = pTerm->pExpr; + pNew->wsFlags |= WHERE_COLUMN_IN; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ + nIn = 25; + }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ + /* "x IN (value, value, ...)" */ + nIn = pExpr->x.pList->nExpr; + } + pNew->nEq++; + pNew->nOut = (double)pProbe->aiRowEst[pNew->nEq] * nInMul * nIn; + }else if( pTerm->eOperator & (WO_EQ|WO_ISNULL) ){ + pNew->wsFlags |= WHERE_COLUMN_EQ; + pNew->nEq++; + pNew->nOut = (double)pProbe->aiRowEst[pNew->nEq] * nInMul; + }else if( pTerm->eOperator & (WO_GT|WO_GE) ){ + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; + pNew->nOut = savedLoop.nOut/3; + }else if( pTerm->eOperator & (WO_LT|WO_LE) ){ + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; + pNew->nOut = savedLoop.nOut/3; } + pNew->rRun = pNew->nOut + estLog(pProbe->aiRowEst[0])*nIn; whereLoopInsert(pBuilder->pWInfo, pNew); - if( pNew->nEqnColumn ){ - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul); + if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->nEqnColumn ){ + whereLoopAddBtreeIndex(pBuilder, maskSelf, pSrc, pProbe, nInMul*nIn); } } *pNew = savedLoop; @@ -5222,10 +5256,12 @@ static void whereLoopAddBtree( struct SrcList_item *pSrc; /* The FROM clause btree term to add */ sqlite3 *db; /* The database connection */ WhereLoop *pNew; /* Template WhereLoop object */ + Bitmask maskSelf; /* Mask for iTab */ pNew = pBuilder->pNew; db = pBuilder->db; pSrc = pBuilder->pTabList->a + iTab; + maskSelf = getMask(pBuilder->pWC->pMaskSet, iTab); if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ @@ -5253,6 +5289,19 @@ static void whereLoopAddBtree( pProbe = &sPk; } + /* Insert a full table scan */ + pNew->iTab = iTab; + pNew->nEq = 0; + pNew->nTerm = 0; + pNew->rSetup = (double)0; + pNew->prereq = 0; + pNew->pIndex = 0; + pNew->wsFlags = 0; + pNew->iOb = pNew->nOb = 0; + pNew->rRun = (double)pSrc->pTab->nRowEst; + pNew->nOut = (double)pSrc->pTab->nRowEst; + whereLoopInsert(pBuilder->pWInfo, pNew); + /* Loop over all indices */ for(; pProbe; pProbe=pProbe->pNext){ @@ -5261,27 +5310,32 @@ static void whereLoopAddBtree( pNew->iTab = iTab; pNew->nEq = 0; pNew->nTerm = 0; + if( pProbe->tnum<=0 ){ + /* Integer primary key index */ + pNew->wsFlags = WHERE_IPK; + }else{ + Bitmask m = pSrc->colUsed; + int j; + for(j=pProbe->nColumn-1; j>=0; j--){ + int x = pProbe->aiColumn[j]; + if( xwsFlags = m==0 ? WHERE_IDX_ONLY : 0; + } paTerm = sqlite3DbRealloc(db, pNew->aTerm, (pProbe->nColumn+1)*sizeof(pNew->aTerm[0])); if( paTerm==0 ) break; pNew->aTerm = paTerm; pNew->pIndex = pProbe; - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 1); + whereLoopAddBtreeIndex(pBuilder, maskSelf, pSrc, pProbe, 1); /* If there was an INDEXED BY clause, then only that one index is ** considered. */ if( pSrc->pIndex ) break; } - -#if 0 - /* Insert a full table scan */ - pNew->iTab = iTab; - pNew->rSetup = (double)0; - pNew->rRun = (double)1000000; - pNew->nOut = (double)1000000; - whereLoopInsert(pBuilder->pWInfo, pNew); -#endif } /* @@ -5578,16 +5632,16 @@ WhereInfo *sqlite3WhereBegin( struct SrcList_item *pItem = pTabList->a + p->iTab; Table *pTab = pItem->pTab; sqlite3DebugPrintf("%02d.%0*llx", p->iTab, nb, p->prereq); - sqlite3DebugPrintf(" %5s", + sqlite3DebugPrintf(" %6s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( p->pIndex ){ - sqlite3DebugPrintf(".%-5s %2d", p->pIndex->zName, p->nEq); + sqlite3DebugPrintf(".%-8s %2d", p->pIndex->zName, p->nEq); }else{ - sqlite3DebugPrintf("%9s",""); + sqlite3DebugPrintf("%12s",""); } sqlite3DebugPrintf(" fg %08x OB %d,%d N %2d", p->wsFlags, p->iOb, p->nOb, p->nTerm); - sqlite3DebugPrintf(" cost %.2g+%.2g,%.2g\n", + sqlite3DebugPrintf(" cost %.4g,%.4g,%.4g\n", p->prereq, p->rSetup, p->rRun, p->nOut); } }