Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge multiple changes from trunk to address concerns with window-function parse-tree rewriting. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | branch-3.32-early-winfunc-rewrite |
Files: | files | file ages | folders |
SHA3-256: |
05418b2a4a6e6a94fa5abd9f944289cf |
User & Date: | drh 2020-06-06 20:48:26 |
Context
2020-06-07
| ||
00:51 | Extra steps to ensure that queries that involve both window functions and aggregate functions are processed correctly by sqlite3WindowRewrite(). Fix for ticket [e5504e987e419fb0]. (Leaf check-in: 765bbcce user: drh tags: branch-3.32-early-winfunc-rewrite) | |
2020-06-06
| ||
20:48 | Merge multiple changes from trunk to address concerns with window-function parse-tree rewriting. (check-in: 05418b2a user: drh tags: branch-3.32-early-winfunc-rewrite) | |
19:54 | Fix a possible ASAN violation inside of debug-only code following an OOM. (check-in: 0e021887 user: drh tags: early-winfunc-rewrite-dev) | |
19:35 | When determining if the subquery inserted by the window-function rewriter is an aggregate query, aggregate functions that are in parameters to another window function do not count. Fix for ticket [1f6f353b684fc708] (check-in: 8583c348 user: drh tags: early-winfunc-rewrite-dev) | |
18:34 | In the query flattener, defer deleting content until after associated Parse object is destroyed, in case some of the deleted expressions have been collected for use by sAggInfo. (check-in: 03b32be4 user: drh tags: early-winfunc-rewrite-dev) | |
14:58 | Remove an incorrect assert() added earlier today. (check-in: 3926ff17 user: drh tags: early-winfunc-rewrite-dev) | |
14:44 | When rewriting the parse-tree for window functions, ensure that the inserted subqueries have an accurate SF_Aggregate bit set. This change also coincidentally fixes ticket [0899cf62f597d7e7], even thought that was not the issue we were working on at the time. (check-in: 2cddb24e user: drh tags: early-winfunc-rewrite-dev) | |
14:29 | Fix an assert() failure that could occur if an ORDER BY expression attached to a compound query contains a subquery that (a) is itself a compound query, (b) uses window functions and (c) has an ORDER BY clause that includes another sub-query. (check-in: c96914ea user: dan tags: early-winfunc-rewrite-dev) | |
13:29 | Avoid no-op calls to sqlite3SelectPrep() when processing sqlite3Select() for subqueries. This simplifies the ".selecttrace" debugging output. (check-in: 3de19ee2 user: drh tags: early-winfunc-rewrite-dev) | |
2020-06-05
| ||
18:17 | Assign a fake name to the ephemeral subquery tables that are created when making parse-tree changes for window functions. (check-in: c4072267 user: drh tags: early-winfunc-rewrite-dev) | |
15:56 | Do parse-tree transformations required for window functions prior to running aggregate function analysis. Fix for ticket [c8d3b9f0a750a529]. (check-in: 79eff1d0 user: drh tags: branch-3.32-early-winfunc-rewrite) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
208 209 210 211 212 213 214 | sqlite3AutoincrementBegin(pParse); /* Code constant expressions that where factored out of inner loops */ if( pParse->pConstExpr ){ ExprList *pEL = pParse->pConstExpr; pParse->okConstFactor = 0; for(i=0; i<pEL->nExpr; i++){ | > > | > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | sqlite3AutoincrementBegin(pParse); /* Code constant expressions that where factored out of inner loops */ if( pParse->pConstExpr ){ ExprList *pEL = pParse->pConstExpr; pParse->okConstFactor = 0; for(i=0; i<pEL->nExpr; i++){ int iReg = pEL->a[i].u.iConstExprReg; if( iReg>0 ){ sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg); } } } /* Finally, jump back to the beginning of the executable code. */ sqlite3VdbeGoto(v, 1); } } |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 | pNC2 = pNC2->pNext; } assert( pDef!=0 || IN_RENAME_OBJECT ); if( pNC2 && pDef ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); | < | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 | pNC2 = pNC2->pNext; } assert( pDef!=0 || IN_RENAME_OBJECT ); if( pNC2 && pDef ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); } } pNC->ncFlags |= savedAllowFlags; } /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 | Expr *pE /* The specific ORDER BY term */ ){ int i; /* Loop counter */ ExprList *pEList; /* The columns of the result set */ NameContext nc; /* Name context for resolving pE */ sqlite3 *db; /* Database connection */ int rc; /* Return code from subprocedures */ | < > > | > > > > | | > | > | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 | Expr *pE /* The specific ORDER BY term */ ){ int i; /* Loop counter */ ExprList *pEList; /* The columns of the result set */ NameContext nc; /* Name context for resolving pE */ sqlite3 *db; /* Database connection */ int rc; /* Return code from subprocedures */ assert( sqlite3ExprIsInteger(pE, &i)==0 ); pEList = pSelect->pEList; /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; nc.ncFlags = NC_AllowAgg|NC_UEList; nc.nErr = 0; db = pParse->db; assert( pParse->nErr==0 ); rc = sqlite3ResolveExprNames(&nc, pE); /* Discard any error. The only error that can occur in the above call ** that we care about is SQLITE_NOMEM, the occurence of which is recorded in ** db->mallocFailed. */ assert( rc!=SQLITE_NOMEM || db->mallocFailed ); if( IN_RENAME_OBJECT==0 ){ sqlite3DbFree(db, pParse->zErrMsg); pParse->zErrMsg = 0; pParse->nErr = 0; } if( rc ) return 0; /* Try to match the ORDER BY expression against an expression ** in the result set. Return an 1-based index of the matching ** result-set entry. */ for(i=0; i<pEList->nExpr; i++){ |
︙ | ︙ | |||
1303 1304 1305 1306 1307 1308 1309 | ** case. This allows the code in alter.c to modify column ** refererences within the ORDER BY expression as required. */ if( IN_RENAME_OBJECT ){ pDup = pE; }else{ pDup = sqlite3ExprDup(db, pE, 0); } | | | 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 | ** case. This allows the code in alter.c to modify column ** refererences within the ORDER BY expression as required. */ if( IN_RENAME_OBJECT ){ pDup = pE; }else{ pDup = sqlite3ExprDup(db, pE, 0); } if( !db->mallocFailed && !pParse->nErr ){ assert(pDup); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); } if( !IN_RENAME_OBJECT ){ sqlite3ExprDelete(db, pDup); } } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
164 165 166 167 168 169 170 | }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); } assert( pNew!=&standin ); return pNew; } | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); } assert( pNew!=&standin ); return pNew; } /* ** Delete the given Select structure and all of its substructures. */ void sqlite3SelectDelete(sqlite3 *db, Select *p){ if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); } /* ** Make arrangements to delete a subquery when the Parse object is ** destroyed. ** ** This works by adding the subquery to the Parse.pConstExpr list, but ** with a register number of zero. The pConstExpr list is destroyed ** when the Parse object is destroyed. And the zero register means ** that the expression is not coded. */ void sqlite3SelectDeferredDelete(Parse *pParse, Select *p){ Expr *pNew = sqlite3PExpr(pParse, TK_SELECT, 0, 0); if( pNew==0 ){ clearSelect(pParse->db, p, 1); }else{ sqlite3PExprAddSelect(pParse, pNew, p); pParse->pConstExpr = sqlite3ExprListAppend(pParse, pParse->pConstExpr, pNew); testcase( pParse->pConstExpr==0 ); /* Only true following OOM */ #ifdef SQLITE_DEBUG if( pParse->pConstExpr ){ ExprList *p = pParse->pConstExpr; struct ExprList_item *pItem = &p->a[p->nExpr-1]; assert( pItem->reusable==0 ); assert( pItem->u.iConstExprReg==0 ); } #endif } } /* ** Delete all the substructure for p, but keep p allocated. Redefine ** p to be a single SELECT where every column of the result set has a ** value of NULL. */ void sqlite3SelectReset(Parse *pParse, Select *p){ |
︙ | ︙ | |||
4148 4149 4150 4151 4152 4153 4154 | recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]); } } /* Finially, delete what is left of the subquery and return ** success. */ | | | 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 | recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]); } } /* Finially, delete what is left of the subquery and return ** success. */ sqlite3SelectDeferredDelete(pParse, pSub1); #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p,("After flattening:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif |
︙ | ︙ | |||
5776 5777 5778 5779 5780 5781 5782 | pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo); /* If ORDER BY makes no difference in the output then neither does ** DISTINCT so it can be removed too. */ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; p->selFlags &= ~SF_Distinct; } | > | | | | | | | | | > | 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 | pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo); /* If ORDER BY makes no difference in the output then neither does ** DISTINCT so it can be removed too. */ sqlite3ExprListDelete(db, p->pOrderBy); p->pOrderBy = 0; p->selFlags &= ~SF_Distinct; } if( (p->selFlags & SF_HasTypeInfo)==0 ){ sqlite3SelectPrep(pParse, p, 0); if( pParse->nErr || db->mallocFailed ){ goto select_end; } assert( p->pEList!=0 ); #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif } if( pDest->eDest==SRT_Output ){ generateColumnNames(pParse, p); } pTabList = p->pSrc; isAgg = (p->selFlags & SF_Aggregate)!=0; |
︙ | ︙ | |||
6206 6207 6208 6209 6210 6211 6212 | sqlite3WindowCodeInit(pParse, p); } #endif assert( WHERE_USE_LIMIT==SF_FixedLimit ); /* Begin the database scan. */ | | | 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 | sqlite3WindowCodeInit(pParse, p); } #endif assert( WHERE_USE_LIMIT==SF_FixedLimit ); /* Begin the database scan. */ SELECTTRACE(1,pParse,p,("WhereBegin-A\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); } if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){ |
︙ | ︙ | |||
6437 6438 6439 6440 6441 6442 6443 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); | | | 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin-B\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 ); if( pWInfo==0 ) goto select_end; if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be |
︙ | ︙ | |||
6712 6713 6714 6715 6716 6717 6718 | ** minMaxFlag will have been previously set to either ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will ** be an appropriate ORDER BY expression for the optimization. */ assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); | | | 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 | ** minMaxFlag will have been previously set to either ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will ** be an appropriate ORDER BY expression for the optimization. */ assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); SELECTTRACE(1,pParse,p,("WhereBegin-C\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ goto select_end; } updateAccumulator(pParse, regAcc, &sAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); |
︙ | ︙ | |||
6767 6768 6769 6770 6771 6772 6773 | /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: sqlite3ExprListDelete(db, pMinMaxOrderBy); sqlite3DbFree(db, sAggInfo.aCol); #ifdef SQLITE_DEBUG | > | | | | > | 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 | /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: sqlite3ExprListDelete(db, pMinMaxOrderBy); sqlite3DbFree(db, sAggInfo.aCol); #ifdef SQLITE_DEBUG if( db->mallocFailed==0 ){ for(i=0; i<sAggInfo.nFunc; i++){ assert( sAggInfo.aFunc[i].pExpr!=0 ); assert( sAggInfo.aFunc[i].pExpr->pAggInfo==&sAggInfo ); sAggInfo.aFunc[i].pExpr->pAggInfo = 0; } } sAggInfo.iAggMagic = 0; #endif sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif ExplainQueryPlanPop(pParse); return rc; } |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 | void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Expr*, int, int, u8); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u32,Expr*); void sqlite3SelectDelete(sqlite3*, Select*); void sqlite3SelectReset(Parse*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif | > | 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 | void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Expr*, int, int, u8); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u32,Expr*); void sqlite3SelectDelete(sqlite3*, Select*); void sqlite3SelectDeferredDelete(Parse*, Select*); void sqlite3SelectReset(Parse*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif |
︙ | ︙ |
Changes to src/window.c.
︙ | ︙ | |||
919 920 921 922 923 924 925 926 927 | /* ** When rewriting a query, if the new subquery in the FROM clause ** contains TK_AGG_FUNCTION nodes that refer to an outer query, ** then we have to increase the Expr->op2 values of those nodes ** due to the extra subquery layer that was added. ** ** See also the incrAggDepth() routine in resolve.c */ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){ | > > > > > | | < | > > > > > | 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | /* ** When rewriting a query, if the new subquery in the FROM clause ** contains TK_AGG_FUNCTION nodes that refer to an outer query, ** then we have to increase the Expr->op2 values of those nodes ** due to the extra subquery layer that was added. ** ** See also the incrAggDepth() routine in resolve.c ** ** In addition to increasing pExpr->op2, set pWalker->eCode to 1 if ** any top-level aggregate functions are encountered. This is needed ** to accurately set the SF_Aggregate flag on the new window-function ** subquery. */ static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_AGG_FUNCTION ){ if( pExpr->op2>=pWalker->walkerDepth ){ pExpr->op2++; }else if( pExpr->op2==pWalker->walkerDepth-1 ){ pWalker->eCode = 1; } }else if( ExprHasProperty(pExpr, EP_WinFunc) ){ return WRC_Prune; } return WRC_Continue; } /* ** If the SELECT statement passed as the second argument does not invoke ** any SQL window functions, this function is a no-op. Otherwise, it |
︙ | ︙ | |||
952 953 954 955 956 957 958 | Expr *pHaving = p->pHaving; ExprList *pSort = 0; ExprList *pSublist = 0; /* Expression list for sub-query */ Window *pMWin = p->pWin; /* Master window object */ Window *pWin; /* Window object iterator */ Table *pTab; | < | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 | Expr *pHaving = p->pHaving; ExprList *pSort = 0; ExprList *pSublist = 0; /* Expression list for sub-query */ Window *pMWin = p->pWin; /* Master window object */ Window *pWin; /* Window object iterator */ Table *pTab; pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ){ return sqlite3ErrorToParser(db, SQLITE_NOMEM); } p->pSrc = 0; |
︙ | ︙ | |||
1043 1044 1045 1046 1047 1048 1049 | if( p->pSrc ){ Table *pTab2; Walker w; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); pSub->selFlags |= SF_Expanded; pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); | < > > > | 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | if( p->pSrc ){ Table *pTab2; Walker w; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); pSub->selFlags |= SF_Expanded; pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); if( pTab2==0 ){ /* Might actually be some other kind of error, but in that case ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get ** the correct error message regardless. */ rc = SQLITE_NOMEM; }else{ memcpy(pTab, pTab2, sizeof(Table)); pTab->tabFlags |= TF_Ephemeral; assert( pTab->zName==0 ); pTab->zName = sqlite3MPrintf(db, "$wintab_%p", pTab); p->pSrc->a[0].pTab = pTab; pTab = pTab2; memset(&w, 0, sizeof(w)); w.xExprCallback = sqlite3WindowExtraAggFuncDepth; w.xSelectCallback = sqlite3WalkerDepthIncrease; w.xSelectCallback2 = sqlite3WalkerDepthDecrease; sqlite3WalkSelect(&w, pSub); if( w.eCode ) pSub->selFlags |= SF_Aggregate; } }else{ sqlite3SelectDelete(db, pSub); } if( db->mallocFailed ) rc = SQLITE_NOMEM; sqlite3DbFree(db, pTab); } |
︙ | ︙ |
Changes to test/window1.test.
︙ | ︙ | |||
1781 1782 1783 1784 1785 1786 1787 1788 1789 | HAVING (SELECT COUNT()OVER() + lead(b)OVER(ORDER BY SUM(DISTINCT b) + b)) ) FROM a UNION SELECT 99 ORDER BY 1; } {99} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 | HAVING (SELECT COUNT()OVER() + lead(b)OVER(ORDER BY SUM(DISTINCT b) + b)) ) FROM a UNION SELECT 99 ORDER BY 1; } {99} #------------------------------------------------------------------------ reset_db do_execsql_test 56.1 { CREATE TABLE t1(a, b INTEGER); CREATE TABLE t2(c, d); } do_catchsql_test 56.2 { SELECT avg(b) FROM t1 UNION ALL SELECT min(c) OVER () FROM t2 ORDER BY nosuchcolumn; } {1 {1st ORDER BY term does not match any column in the result set}} reset_db do_execsql_test 57.1 { CREATE TABLE t4(a, b, c, d, e); } do_catchsql_test 57.2 { SELECT b FROM t4 UNION SELECT a FROM t4 ORDER BY ( SELECT sum(x) OVER() FROM ( SELECT c AS x FROM t4 UNION SELECT d FROM t4 ORDER BY (SELECT e FROM t4) ) ); } {1 {1st ORDER BY term does not match any column in the result set}} # 2020-06-06 various dbsqlfuzz finds and # ticket 0899cf62f597d7e7 # reset_db do_execsql_test 57.1 { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(NULL,NULL,NULL); SELECT sum(a), min(b) OVER (), count(c) OVER (ORDER BY b) FROM t1; } {{} {} 0} do_execsql_test 57.2 { CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ; INSERT INTO v0 VALUES ( 10 ) ; SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2; } {10 {}} do_execsql_test 57.3 { DROP TABLE t1; CREATE TABLE t1(a); INSERT INTO t1(a) VALUES(22); CREATE TABLE t3(y); INSERT INTO t3(y) VALUES(5),(11),(-9); SELECT ( SELECT max(y) OVER( ORDER BY (SELECT x FROM (SELECT sum(y) AS x FROM t1))) ) FROM t3; } {5} # 2020-06-06 ticket 1f6f353b684fc708 reset_db do_execsql_test 58.1 { CREATE TABLE a(a, b, c); INSERT INTO a VALUES(1, 2, 3); INSERT INTO a VALUES(4, 5, 6); SELECT sum(345+b) OVER (ORDER BY b), sum(avg(678)) OVER (ORDER BY c) FROM a; } {347 678.0} finish_test |