-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
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
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
# 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.
**
}
#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: