-C Change\sreferences\sto\sthe\sschema\stable\sin\ssqlite3_analyzer\sto\sthe\snew\nSQLITE_SCHEMA\sname.
-D 2021-07-15T16:39:42.407
+C Attempt\sto\somit\sORDER\sBY\sclauses\sfrom\sFROM-clause\ssubqueries\sif\sthose\sORDER\sBY\nclauses\sdo\snot\saffect\sthe\soutput.\s\sSee\n[forum:/forumpost/2d76f2bcf65d256a|forum\sthread\s2d76f2bcf65d256a]\sfor\ndiscussion.\s\sThis\scan\shelp\sthe\squery\sflattener\sin\nsome\scases,\sresulting\sin\sfaster\squery\splans.\s\sThe\scurrent\simplemention\sdoes\nnot\salways\swork.
+D 2021-07-15T19:29:43.004
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/expr.c 62b6d0ac8ee30a4749b78b7b75ae951a911a5d49321af5fe41c05af4df9e7537
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
-F src/func.c c96ac6f7c4f2d684217c4673a80446e1b50e25b5ea79366f333f484622d010a0
+F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c
F src/global.c 25ba4d58476f6be29bba9d9d14f7f146b78476d3a4d75ebb8c3b736328afe0f9
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67
F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
-F src/resolve.c b379c5ffe3b692e9c64fa37817cc0efa204b7c9468a818309dde85fd132d9d81
+F src/resolve.c 9b54a60702c35b3efbeb5d0439a94d67c4cb93a896e1afa89f21d7a9d183a071
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 1c1230aaa4e5979edd3c5a9f7a90ab856a302cca4962e8a7d08f42dd2e7e1a49
+F src/select.c cc61c6b86617387803d67994fec6131365f6a049399aa28b11028ad0b4ee53b8
F src/shell.c.in 856de2945bb7fdfdeebe7136cf1b59d24618845aa5e5f3937fda7ff37c623b51
F src/sqlite.h.in a5d5641afa335226231231c7b6e424de327f17577d9e8aeaaaab78d9bbbcf381
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
-F src/sqliteInt.h 129619232aa632fa85db7792bfe4b378ed28d3361bf9cbcdb4522353fd04b89b
+F src/sqliteInt.h 74ca9667448fa7aaadcb91bd3fd22732c7f7e05903a53429e653a4a01e4c8efd
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
F src/wherecode.c 9f1f65d11437b25cd0a1497a170514c785f19ce6ad9d3e6fc73719cb5a49012f
F src/whereexpr.c 2bfb1cd24b9b63fc5e32b9b85f2b3f88765bdac2aab51102d94d1fb56ec2917b
-F src/window.c 559961a731f67a0873744960bdeeb034a5c74cc0a09badb14bc43f74744a2a9d
+F src/window.c 420167512050a0dfc0f0115b9f0c7d299da9759c9bb2ae83a61fb8d730a5707f
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1594056aab068b9fae82f6b885828c7127d9bedcc37c4340486e32791bc87c7a
-R 559c73747c40f0a1a7e76968f3947fcc
+P 3beb77d6a792d07ca605ec8e5402b8a305860cba4044fcafeed00b9fa862fa16
+R be1da55dd559418ff2dfd4ecbe7a006e
+T *branch * omit-subquery-order-by
+T *sym-omit-subquery-order-by *
+T -sym-trunk *
U drh
-Z 82febd786cf0b2a285b7ed5af3f23080
+Z fa9c090cb9dd3863cd70130aca6f84ef
-3beb77d6a792d07ca605ec8e5402b8a305860cba4044fcafeed00b9fa862fa16
\ No newline at end of file
+ef97c3e7c3ea2cf1a4db6591328fe7ce3f1d189afc2d578159135824ec89e620
\ No newline at end of file
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
- SQLITE_FUNC_MINMAX ),
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
- SQLITE_FUNC_MINMAX ),
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ),
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
WAGGREGATE(count, 0,0,0, countStep,
- countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
+ countFinalize, countFinalize, countInverse,
+ SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
WAGGREGATE(count, 1,0,0, countStep,
- countFinalize, countFinalize, countInverse, 0 ),
+ countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
+ assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
-
+ testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
+ pNC2->ncFlags |= NC_HasAgg
+ | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
+ & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
}
}
pNC->ncFlags |= savedAllowFlags;
pGroupBy = p->pGroupBy;
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
assert( NC_MinMaxAgg==SF_MinMaxAgg );
- p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
+ assert( NC_OrderAgg==SF_OrderByReqd );
+ p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg));
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
Walker w;
if( pExpr==0 ) return SQLITE_OK;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback = resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
if( pExpr==0 ) continue;
assert( EP_Win==NC_HasWin );
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
- if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
+ if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
- savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg |= pNC->ncFlags &
+ (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
}
if( w.pParse->nErr>0 ) return WRC_Abort;
}
if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
assert( pSub->pGroupBy==0 );
+ /* If a FROM-clause subquery has an ORDER BY clause that is not
+ ** really doing anything, then delete it now so that it does not
+ ** interfere with query flattening.
+ **
+ ** Beware of these cases where the ORDER BY clause may not be safely
+ ** omitted:
+ **
+ ** (1) There is also a LIMIT clause
+ ** (2) The subquery was added to help with window-function
+ ** processing
+ ** (3) The outer query uses an aggregate function other than
+ ** the built-in count(), min(), or max().
+ */
+ if( pSub->pOrderBy!=0
+ && pSub->pLimit==0 /* Condition (1) */
+ && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
+ && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) */
+ && OptimizationEnabled(db, SQLITE_OmitOrderBy)
+ ){
+ SELECTTRACE(0x100,pParse,p,
+ ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
+ sqlite3ExprListDelete(db, pSub->pOrderBy);
+ pSub->pOrderBy = 0;
+ }
+
/* If the outer query contains a "complex" result set (that is,
** if the result set of the outer query uses functions or subqueries)
** and if the subquery contains an ORDER BY clause and if
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
+#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** are assert() statements in the code to verify this.
**
** Value constraints (enforced via assert()):
-** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
-** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
-** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
-** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
-** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
-** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
+** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
+** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
+** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
+** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
+** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
/* Identifier numbers for each in-line function */
#define INLINEFUNC_coalesce 0
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
-** NC_HasAgg == SF_HasAgg == EP_Agg
-** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_HasAgg == SF_HasAgg == EP_Agg
+** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
** NC_HasWin == EP_Win
**
*/
-#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
-#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
-#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
-#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
-#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
-#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
-#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
-#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
-#define NC_UEList 0x00080 /* True if uNC.pEList is used */
-#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
-#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
-#define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
-#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x02000 /* True if a function or subquery seen */
-#define NC_AllowWin 0x04000 /* Window functions are allowed here */
-#define NC_HasWin 0x08000 /* One or more window functions seen */
-#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
-#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
-#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
-#define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
+#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
+#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
+#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
+#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
+#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
+#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
+#define NC_VarSelect 0x000040 /* A correlated subquery has been seen */
+#define NC_UEList 0x000080 /* True if uNC.pEList is used */
+#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
+#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
+#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
+#define NC_Complex 0x002000 /* True if a function or subquery seen */
+#define NC_AllowWin 0x004000 /* Window functions are allowed here */
+#define NC_HasWin 0x008000 /* One or more window functions seen */
+#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
+#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
+#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
+#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
** An instance of the following object describes a single ON CONFLICT
** "Select Flag".
**
** Value constraints (all checked via assert())
-** SF_HasAgg == NC_HasAgg
-** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
-** SF_FixedLimit == WHERE_USE_LIMIT
+** SF_HasAgg == NC_HasAgg
+** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
+** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
+** SF_FixedLimit == WHERE_USE_LIMIT
*/
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
#define SF_All 0x0000002 /* Includes the ALL keyword */
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
+#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be purged */
/*
** The results of a SELECT can be distributed in several ways, as defined
Table *pTab2;
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
- pSub->selFlags |= SF_Expanded;
+ pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
pSub->selFlags |= (selFlags & SF_Aggregate);
if( pTab2==0 ){