From: drh Date: Wed, 5 Jul 2017 14:54:24 +0000 (+0000) Subject: Add the count-of-view optimization when compiled using X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=23a09adc0b97000fdcc8d95278f6dd6a11d8c459;p=thirdparty%2Fsqlite.git Add the count-of-view optimization when compiled using SQLITE_COUNTOFVIEW_OPTIMIZATION. FossilOrigin-Name: b7ae4b879fc086e9543493843377ae90ceff1fe49c97b4c23367012034c3c9d5 --- diff --git a/manifest b/manifest index bec6e52361..d0b3c3e3d1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_DEFAULT_ROWEST\scompile-time\soption\sfor\schanging\sthe\sestimated\nnumber\sof\srows\sin\stables\sthat\slack\ssqlite_stat1\sentries. -D 2017-06-06T18:22:05.443 +C Add\sthe\scount-of-view\soptimization\swhen\scompiled\susing\s\nSQLITE_COUNTOFVIEW_OPTIMIZATION. +D 2017-07-05T14:54:24.911 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,12 +230,12 @@ F src/printf.c 8ae1fa9d30c1200a9268a390ba9e9cea9197b27a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 41aa91af56d960e9414ce1d7c17cfb68e0d1c6cb F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c ec96f4cdc5c39b83f54d8e0cf96bf91f2bb6fac0 +F src/select.c 296bf898a2d845ca9b58bf936e42b1122eab3cfab03848da0f684150548ff8a2 F src/shell.c 84a1593bd86aaa14f4da8a8f9b16fbc239d262aa F src/sqlite.h.in 278602140d49575e8708e643161f4263e428a02a F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h 81198400a63a72ac2864421a7be78172abe5cecf +F src/sqliteInt.h 3b055fff776a257d0b2473edec5e121db8724c51c1034452c1be3b0faaf02f45 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -1250,8 +1250,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 19dad0a720c41d1d111f42cb2cb1f291c559957e76e3f88dc6cfc065e4845e77 -Q +234ede26e30f20e6c33002739ed8be35dbfb5c77700bd857ff31072b9b7df347 -R 0abd2b13af71300bd2b7a8ab9ad2e7ec +P 802b82f342328762e3995825aed1b22e61361ef24b673cd5d66b55756ce2a461 +Q +d1ba200234f40b84327c7fc28c2584ed069da80e97578df71114d1a9ba9c559c +R d1ab17963b33badcbff62fa608fc3eef U drh -Z c7d056a26cdd67a2c8fba47da44b2255 +Z 7c072e36d0f6a6f55c9a69a4c236ee0f diff --git a/manifest.uuid b/manifest.uuid index 5c6ecff159..6b7c324175 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -802b82f342328762e3995825aed1b22e61361ef24b673cd5d66b55756ce2a461 \ No newline at end of file +b7ae4b879fc086e9543493843377ae90ceff1fe49c97b4c23367012034c3c9d5 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 4788064597..8d31da3ddc 100644 --- a/src/select.c +++ b/src/select.c @@ -4710,6 +4710,94 @@ static void explainSimpleCount( # define explainSimpleCount(a,b,c) #endif +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION +/* +** Attempt to transform a query of the form +** +** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) +** +** Into this: +** +** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) +** +** The transformation only works if all of the following are true: +** +** * The subquery is a UNION ALL of two or more terms +** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries +** * The outer query is a simple count(*) +** +** Return TRUE if the optimization is undertaken. +*/ +static int countOfViewOptimization(Parse *pParse, Select *p){ + Select *pSub, *pPrior; + Expr *pExpr; + Expr *pCount; + sqlite3 *db; + if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */ + if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ + pExpr = p->pEList->a[0].pExpr; + if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ + if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */ + if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ + if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */ + pSub = p->pSrc->a[0].pSelect; + if( pSub==0 ) return 0; /* The FROM is a subquery */ + if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */ + do{ + if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ + if( pSub->pWhere ) return 0; /* No WHERE clause */ + if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */ + pSub = pSub->pPrior; /* Repeat over compound terms */ + }while( pSub ); + + /* If we reach this point, that means it is OK to perform the transformation */ + + db = pParse->db; + pCount = pExpr; + pExpr = 0; + pSub = p->pSrc->a[0].pSelect; + p->pSrc->a[0].pSelect = 0; + sqlite3SrcListDelete(db, p->pSrc); + p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc)); + while( pSub ){ + Expr *pTerm; + pPrior = pSub->pPrior; + pSub->pPrior = 0; + pSub->pNext = 0; + pSub->selFlags |= SF_Aggregate; + pSub->selFlags &= ~SF_Compound; + pSub->nSelectRow = 0; + sqlite3ExprListDelete(db, pSub->pEList); + pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; + pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); + pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( pTerm ){ + pTerm->x.pSelect = pSub; + ExprSetProperty(pTerm, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, pTerm); + if( pExpr==0 ){ + pExpr = pTerm; + }else{ + pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr, 0); + } + }else{ + sqlite3SelectDelete(db, pSub); + } + pSub = pPrior; + } + p->pEList->a[0].pExpr = pExpr; + p->selFlags &= ~SF_Aggregate; + +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + return 1; +} +#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */ + /* ** Generate code for the SELECT statement given in the p argument. ** @@ -4933,6 +5021,16 @@ int sqlite3Select( } #endif +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION + if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) + && countOfViewOptimization(pParse, p) + ){ + if( db->mallocFailed ) goto select_end; + pEList = p->pEList; + pTabList = p->pSrc; + } +#endif + /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and ** if the select-list is the same as the ORDER BY list, then this query ** can be rewritten as a GROUP BY. In other words, this: diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c7d729cf35..27f442ea92 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1245,6 +1245,7 @@ struct sqlite3 { #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ +#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /*