From: dan Date: Thu, 14 Jun 2018 19:06:36 +0000 (+0000) Subject: Fix problem with window functions min() and max() when used with a PARTITION X-Git-Tag: version-3.25.0~178^2~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9a94722d489becb6b9023b0119a55995cc998de6;p=thirdparty%2Fsqlite.git Fix problem with window functions min() and max() when used with a PARTITION clause and a frame starting point other than "UNBOUNDED PRECEDING". FossilOrigin-Name: 43eb1e75a4d7ac0973ed8589bbaf379c24cdc8eacc4e613610d2d4c24d385dc1 --- diff --git a/manifest b/manifest index f68fad8115..fa813d09b4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. -D 2018-06-14T14:30:51.987 +C Fix\sproblem\swith\swindow\sfunctions\smin()\sand\smax()\swhen\sused\swith\sa\sPARTITION\nclause\sand\sa\sframe\sstarting\spoint\sother\sthan\s"UNBOUNDED\sPRECEDING". +D 2018-06-14T19:06:36.904 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 498b77b89a8cb42f2ee20fcd6317f279a45c0d6ff40d27825f94b69884c09bbe @@ -431,7 +431,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 819b14b58e71565f8da505a9c1d5d9d904605f85cd64179cf9c7d1edcdad6c25 F src/analyze.c 41f0b8d638fc2a7309477904ac38e535f2aabea3256da3251e529730e099df77 -F src/attach.c 3af6abc40733d10014b401c89a4e8ecfa7c3855517c62004461875220a3af453 +F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -495,12 +495,12 @@ F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c a8cf3d6144f6a821f002dad72f80659691e827a96e6da6dedf8b263edefe3a80 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 224312eb28c1170117c8cef29abc8f6a420b2a60df26543df75632b731ecac8d +F src/select.c 7e8e439bf8bf732860566ccceebd57d934bf1aceca213c394d825dde60473f8e F src/shell.c.in 8578421c5fb2a972461b2a996f7173646e55e0dbd2a2eee30c8f5dc7d3dbadfd F src/sqlite.h.in 19de593baa0667854730e7b8bc2e3039c20ee80a4d537e9b5ec2038947fe3daf F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 -F src/sqliteInt.h f6c6b3b9690c6e3cb35b482deb4873dddb16fc127d97ce99b103ba5793b78640 +F src/sqliteInt.h 97525ef265cfca3cf39c87b73dd1e39f9260ee2f25fb0cee64bbbe26eb9f3888 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -565,13 +565,13 @@ F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c f68624da05fefc48eb663c3ceaba4fd9a999b8f9a15b957312e42ceb687a3622 +F src/vdbe.c 55bc870dcab52f7eac5a84d84e13e68122308997975d066f450a42c24d80df32 F src/vdbe.h 9c8c245fa3785266c269ab02c135c836ff49a307612186686bcdae500f409945 F src/vdbeInt.h d99f1c3da17b4ed271efc2f52898dd9a577dee077da47c2a014bc128f3cdba2a F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff F src/vdbeaux.c c2d65c763b0811afe409e02e9d0d1f300c6e97892474fc94eec3da71955cd418 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 -F src/vdbemem.c 7301d5c4f98069aead603c9a5b28e0a8dd793b1c57570d67e45aab6b87bf5fec +F src/vdbemem.c b8f3bb3bed82774ee352fa3405c83de2fc3e528638adfd3d15fa9a0da5c03d07 F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b @@ -583,7 +583,7 @@ F src/where.c 0bcbf9e191ca07f9ea2008aa80e70ded46bcdffd26560c83397da501f00aece6 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96 F src/whereexpr.c 19cf35cdd9bf6d5589d8a5c960d99259761136187a2319a6e14d11cf1abe14c2 -F src/window.c 0a6b366a3301c68172fcdbebd5b9ddf0466cdc6533ff92ad859b4acd06aaa29b +F src/window.c 3fc03f5ac20516d218933bc9eaf37863a511d9b9fffb3e37a9409e7a25efca99 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1149,7 +1149,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 10793f1de89a226fa22dde9ba9398de22571fee1bfb53a935a11be4aa014704f +F test/permutations.test 5c2167e03dc55ff697e11bb3abf10c66ba452e4afb2dbd85a2b144048355300e F test/pg_common.tcl b50727fe1ee3369d0421eadea2c2fd247bfb9d89a8e06ececf2f6866de17abd8 F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f @@ -1617,13 +1617,13 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 94c626fe8d9eced3e3d5ef0a2106209904daba77d549aafde09eba1db8e98c3e +F test/window1.test 68607fd4cfa24f5cdd6029a63a2a7c062042ff5787fa054aa5c0b006154fe183 F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fba1b F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086 F test/window3.tcl 654d61d73e10db089b22514d498bb23ec310f720c0f4b5f69f67fda83d672048 F test/window3.test 41727668ee31d2ba50f78efcb5bf1bda2c5cffd889aa65243511004669d1ac25 -F test/window4.tcl 09167855f695ef94312da965532bc13f8027411de8ce442664fa74949f9df011 -F test/window4.test eb0cf5740de803a4a9373b2c30b73986a4fb1662149260ccf05458abba312ba5 +F test/window4.tcl 3388b29669144bccd012bf5e237d165cf8eff2a310c26cc43a70279775f2fb01 +F test/window4.test f14ecc20c004a2a0d5fd8530266ea4255e3c0a55681bce1fea24af04ea82005f F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d @@ -1740,7 +1740,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bb915854d435bdd78f141d70e23527e97922ec176acd3ed8060c78dffc96bab8 ee431d55eba618cfba414c3946b3162bc205a70dd4e43d74a7623be332b94c92 -R 1cc4d33069ce5c96e4421646ef097697 +P 5cf5f1808a51f9c2cfc98dd49b4f1ce860b53e935287f89868ce2fdbace8eb06 +R ef2b7f57cdc1146bf754373b3823f53c U dan -Z c65e558489cd4a1cde706d8fb1c8cdef +Z e015141b8a297bc169625a565b97966a diff --git a/manifest.uuid b/manifest.uuid index 7b50e2ba90..fe46aaa166 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5cf5f1808a51f9c2cfc98dd49b4f1ce860b53e935287f89868ce2fdbace8eb06 \ No newline at end of file +43eb1e75a4d7ac0973ed8589bbaf379c24cdc8eacc4e613610d2d4c24d385dc1 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 1f276156b8..42ae536942 100644 --- a/src/attach.c +++ b/src/attach.c @@ -414,7 +414,7 @@ void sqlite3Detach(Parse *pParse, Expr *pDbname){ 0, /* pNext */ detachFunc, /* xSFunc */ 0, /* xFinalize */ - 0, 0, + 0, 0, /* xValue, xInverse */ "sqlite_detach", /* zName */ {0} }; @@ -434,7 +434,7 @@ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ 0, /* pNext */ attachFunc, /* xSFunc */ 0, /* xFinalize */ - 0, 0, + 0, 0, /* xValue, xInverse */ "sqlite_attach", /* zName */ {0} }; diff --git a/src/select.c b/src/select.c index c90a978d1a..a3a85503b5 100644 --- a/src/select.c +++ b/src/select.c @@ -3673,6 +3673,10 @@ static void substSelect( ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** +** (25) If either the subquery or the parent query contains a window +** function in the select list or ORDER BY clause, flattening +** is not attempted. +** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query @@ -3716,7 +3720,7 @@ static int flattenSubquery( pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( p->pWin || pSub->pWin ) return 0; + if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ pSubSrc = pSub->pSrc; assert( pSubSrc ); @@ -4587,12 +4591,20 @@ static void selectPopWith(Walker *pWalker, Select *p){ #define selectPopWith 0 #endif +/* +** The SrcList_item structure passed as the second argument represents a +** sub-query in the FROM clause of a SELECT statement. This function +** allocates and populates the SrcList_item.pTab object. If successful, +** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, +** SQLITE_NOMEM. +*/ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ Select *pSel = pFrom->pSelect; Table *pTab; + assert( pSel ); pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); - if( pTab==0 ) return WRC_Abort; + if( pTab==0 ) return SQLITE_NOMEM; pTab->nTabRef = 1; if( pFrom->zAlias ){ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); @@ -4605,7 +4617,7 @@ int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral; - return WRC_Continue; + return SQLITE_OK; } /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e63cc46890..ce84441a13 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1685,7 +1685,7 @@ struct FuncDestructor { #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */ -#define SQLITE_FUNC_WINDOW_SIZE 0x20000 +#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -3485,6 +3485,10 @@ struct TreeView { }; #endif /* SQLITE_DEBUG */ +/* +** Object used to encode the OVER() clause attached to a window-function +** invocation. And some fields used while generating VM code for the same. +*/ struct Window { char *zName; /* Name of window (may be NULL) */ ExprList *pPartition; /* PARTITION BY clause */ @@ -3524,6 +3528,7 @@ int sqlite3WindowRewrite(Parse*, Select*); int sqlite3ExpandSubquery(Parse*, struct SrcList_item*); void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); +void sqlite3WindowFunctions(void); /* ** Assuming zIn points to the first byte of a UTF-8 character, @@ -4198,7 +4203,6 @@ extern sqlite3_uint64 sqlite3NProfileCnt; void sqlite3RootPageMoved(sqlite3*, int, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterFunctions(void); -void sqlite3WindowFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); diff --git a/src/vdbe.c b/src/vdbe.c index b3f5ffbafd..e2db54dc13 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5082,7 +5082,7 @@ case OP_Sort: { /* jump */ p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } -/* Opcode: Rewind P1 P2 * * * +/* Opcode: Rewind P1 P2 * * P5 ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. @@ -5090,6 +5090,10 @@ case OP_Sort: { /* jump */ ** If the table or index is not empty, fall through to the following ** instruction. ** +** If P5 is non-zero and the table is not empty, then the "skip-next" +** flag is set on the cursor so that the next OP_Next instruction +** executed on it is a no-op. +** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. @@ -6282,24 +6286,24 @@ case OP_DecrJumpZero: { /* jump, in1 */ } -/* Opcode: AggStep0 * P2 P3 P4 P5 +/* Opcode: AggStep0 P1 P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** -** Execute the step function for an aggregate. The -** function has P5 arguments. P4 is a pointer to the FuncDef -** structure that specifies the function. Register P3 is the +** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an +** aggregate. The function has P5 arguments. P4 is a pointer to the +** FuncDef structure that specifies the function. Register P3 is the ** accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. */ -/* Opcode: AggStep * P2 P3 P4 P5 +/* Opcode: AggStep P1 P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** -** Execute the step function for an aggregate. The -** function has P5 arguments. P4 is a pointer to an sqlite3_context -** object that is used to run the function. Register P3 is -** as the accumulator. +** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an +** aggregate. The function has P5 arguments. P4 is a pointer to the +** FuncDef structure that specifies the function. Register P3 is the +** accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. @@ -6388,11 +6392,13 @@ case OP_AggStep: { break; } -/* Opcode: AggFinal P1 P2 * P4 * +/* Opcode: AggFinal P1 P2 P3 P4 * ** Synopsis: accum=r[P1] N=P2 ** -** Execute the finalizer function for an aggregate. P1 is -** the memory location that is the accumulator for the aggregate. +** P1 is the memory location that is the accumulator for an aggregate +** or window function. If P3 is zero, then execute the finalizer function +** for an aggregate and store the result in P1. Or, if P3 is non-zero, +** invoke the xValue() function and store the result in register P3. ** ** P2 is the number of arguments that the step function takes and ** P4 is a pointer to the FuncDef for this function. The P2 diff --git a/src/vdbemem.c b/src/vdbemem.c index b89396d0b7..6e0f8d6e07 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -415,6 +415,14 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ return ctx.isError; } +/* +** Memory cell pAccum contains the context of an aggregate function. +** This routine calls the xValue method for that function and stores +** the results in memory cell pMem. +** +** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK +** otherwise. +*/ int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ sqlite3_context ctx; Mem t; @@ -432,6 +440,7 @@ int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ pFunc->xValue(&ctx); return ctx.isError; } + /* ** If the memory cell contains a value that must be freed by ** invoking the external callback in Mem.xDel, then this routine diff --git a/src/window.c b/src/window.c index 459d05e29e..0ec6bd34f8 100644 --- a/src/window.c +++ b/src/window.c @@ -859,6 +859,13 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *p = pWin->pFunc; if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ + /* The inline versions of min() and max() require a single ephemeral + ** table and 3 registers. The registers are used as follows: + ** + ** regApp+0: slot to copy min()/max() argument to for MakeRecord + ** regApp+1: integer value used to ensure keys are unique + ** regApp+2: output of MakeRecord + */ ExprList *pList = pWin->pOwner->x.pList; KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); pWin->csrApp = pParse->nTab++; @@ -1248,14 +1255,21 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){ int nArg = 0; Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ + FuncDef *pFunc = pWin->pFunc; sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); nArg = MAX(nArg, windowArgCount(pWin)); - if( pWin->pFunc->xSFunc==nth_valueStepFunc - || pWin->pFunc->xSFunc==first_valueStepFunc + if( pFunc->xSFunc==nth_valueStepFunc + || pFunc->xSFunc==first_valueStepFunc ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); } + + if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ + assert( pWin->eStart!=TK_UNBOUNDED ); + sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); + } } regArg = pParse->nMem+1; pParse->nMem += nArg; diff --git a/test/permutations.test b/test/permutations.test index 52e2509fc1..475ad10a65 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -283,6 +283,12 @@ test_suite "fts5-light" -prefix "" -description { -exclude *corrupt* *fault* *big* *fts5aj* ] +test_suite "window" -prefix "" -description { + All window function related tests . +} -files [ + test_set [glob -nocomplain $::testdir/window*.test] +] + test_suite "lsm1" -prefix "" -description { All LSM1 tests. } -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test] diff --git a/test/window1.test b/test/window1.test index 18d547963c..14edd0e031 100644 --- a/test/window1.test +++ b/test/window1.test @@ -251,6 +251,10 @@ do_catchsql_test 7.1.6 { SELECT trim(x) OVER (ORDER BY y) FROM t1; } {1 {trim() may not be used as a window function}} +do_catchsql_test 7.1.7 { + SELECT max(x) OVER abc FROM t1 WINDOW def AS (ORDER BY y); +} {1 {no such window: abc}} + finish_test diff --git a/test/window4.tcl b/test/window4.tcl index 5c7466e75d..e96782afdc 100644 --- a/test/window4.tcl +++ b/test/window4.tcl @@ -128,7 +128,8 @@ execsql_test 3.6.3 { FROM t5 } -#========================================================================= +========== + execsql_test 4.0 { DROP TABLE IF EXISTS ttt; CREATE TABLE ttt(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER); @@ -163,6 +164,57 @@ execsql_test 4.4 { ) FROM ttt; } +set lPart [list "PARTITION BY b" "PARTITION BY b, a" "" "PARTITION BY a"] +set lOrder [list "ORDER BY a" "ORDER BY a DESC" "" "ORDER BY b, a"] +set lRange { + "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" + "BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" + "BETWEEN CURRENT ROW AND CURRENT ROW" + "BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" +} + +set tn 1 +set SQL { + SELECT max(c) OVER ($p1 $o1 RANGE $r1), + min(c) OVER ($p2 $o2 RANGE $r2) + FROM ttt ORDER BY a +} +set SQL2 { + SELECT avg(c) OVER ($p1 $o1 RANGE $r1), + avg(c) OVER ($p2 $o2 RANGE $r2) + FROM ttt ORDER BY a +} + +set o1 [lindex $lOrder 0] +set o2 [lindex $lOrder 0] +set r1 [lindex $lRange 0] +set r2 [lindex $lRange 0] +foreach p1 $lPart { foreach p2 $lPart { + execsql_test 4.5.$tn.1 [subst $SQL] + execsql_float_test 4.5.$tn.2 [subst $SQL2] + incr tn +}} + +set o1 [lindex $lOrder 0] +set o2 [lindex $lOrder 0] +set p1 [lindex $lPart 0] +set p2 [lindex $lPart 0] +foreach r1 $lRange { foreach r2 $lRange { + execsql_test 4.5.$tn.1 [subst $SQL] + execsql_float_test 4.5.$tn.2 [subst $SQL2] + incr tn +}} + +set r1 [lindex $lRange 0] +set r2 [lindex $lRange 0] +set p1 [lindex $lPart 0] +set p2 [lindex $lPart 0] +foreach o1 $lOrder { foreach o2 $lOrder { + execsql_test 4.5.$tn.1 [subst $SQL] + execsql_float_test 4.5.$tn.2 [subst $SQL2] + incr tn +}} + finish_test diff --git a/test/window4.test b/test/window4.test index 20b8a114b0..a57fc16b74 100644 --- a/test/window4.test +++ b/test/window4.test @@ -211,6 +211,8 @@ do_execsql_test 3.6.3 { FROM t5 } {1 one 2 two 3 three 4 four 5 five} +#========================================================================== + do_execsql_test 4.0 { DROP TABLE IF EXISTS ttt; CREATE TABLE ttt(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER); @@ -245,4 +247,772 @@ do_execsql_test 4.4 { ) FROM ttt; } {18 17 15 12 11 9 6 5 3} +do_execsql_test 4.5.1.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.1.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.2.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.2.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.3.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} + +do_test 4.5.3.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 1.50 3.00 2.00 1.50 2.00 2.50 2.20 3.50 2.50 2.00 2.57 3.00 2.75 4.00 3.00} + +do_execsql_test 4.5.4.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.4.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.5.1 { + SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.5.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.6.1 { + SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.6.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.7.1 { + SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} + +do_test 4.5.7.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 1.50 3.00 2.00 2.00 2.00 3.00 2.20 4.00 2.50 3.00 2.57 4.00 2.75 5.00 3.00} + +do_execsql_test 4.5.8.1 { + SELECT max(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.8.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.9.1 { + SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 3 1 3 2 4 3 4 1 4 2 5 3} + +do_test 4.5.9.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 1.50 2.00 2.00 3.00 2.00 1.50 2.20 2.50 2.50 3.50 2.57 2.00 2.75 3.00 3.00 4.00} + +do_execsql_test 4.5.10.1 { + SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 3 2 3 3 4 4 4 3 4 4 5 5} + +do_test 4.5.10.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 1.50 2.00 2.00 3.00 2.00 2.00 2.20 3.00 2.50 4.00 2.57 3.00 2.75 4.00 3.00 5.00} + +do_execsql_test 4.5.11.1 { + SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 1 3 1 3 1 3 1 4 1 4 1 4 1 5 1} + +do_test 4.5.11.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 1.50 1.50 2.00 2.00 2.00 2.00 2.20 2.20 2.50 2.50 2.57 2.57 2.75 2.75 3.00 3.00} + +do_execsql_test 4.5.12.1 { + SELECT max(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 3 2 3 3 4 4 4 3 4 4 5 5} + +do_test 4.5.12.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 1.50 2.00 2.00 3.00 2.00 2.00 2.20 3.00 2.50 4.00 2.57 3.00 2.75 4.00 3.00 5.00} + +do_execsql_test 4.5.13.1 { + SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.13.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.14.1 { + SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.14.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b, a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.15.1 { + SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 1 3 1 2 1 3 1 4 1 3 1 4 1 5 1} + +do_test 4.5.15.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER ( ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 1.50 3.00 2.00 2.00 2.00 3.00 2.20 4.00 2.50 3.00 2.57 4.00 2.75 5.00 3.00} + +do_execsql_test 4.5.16.1 { + SELECT max(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.16.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY a ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.17.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.17.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.18.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.18.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.19.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.19.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.20.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.20.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.50 2.50 3.50 3.50 4.50 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.21.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.21.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.22.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.22.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.23.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.23.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.24.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.24.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.50 3.00 3.50 4.00 4.50 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.25.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.25.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.26.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.26.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.27.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.27.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 2.00 2.00 3.00 3.00 4.00 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.28.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.28.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 2.00 2.50 3.00 3.50 4.00 4.50 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.29.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.29.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.50 1.50 3.50 2.50 4.50 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.30.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.30.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.50 2.00 3.50 3.00 4.50 4.00 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.31.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.31.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.50 2.00 3.50 3.00 4.50 4.00 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.32.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.32.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.50 2.50 3.50 3.50 4.50 4.50 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.33.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.33.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.34.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.34.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.50 2.50 3.50 3.50 4.50 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.35.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.35.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.36.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.36.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.37.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.37.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.50 1.50 3.50 2.50 4.50 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.38.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.38.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.50 2.50 3.50 3.50 4.50 4.50 3.00 3.00 4.00 4.00 5.00 5.00} + +do_execsql_test 4.5.39.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.39.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.50 2.00 3.50 3.00 4.50 4.00 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.40.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.40.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.50 1.50 3.50 2.50 4.50 3.50 3.00 2.00 4.00 3.00 5.00 4.00} + +do_execsql_test 4.5.41.1 { + SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.41.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.42.1 { + SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 2 4 3 5 4 3 3 4 4 5 5} + +do_test 4.5.42.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.50 3.00 3.50 4.00 4.50 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.43.1 { + SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.43.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.00 3.00 3.00 4.00 4.00 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.44.1 { + SELECT max(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {3 1 4 2 5 3 3 1 4 2 5 3 3 1 4 2 5 3} + +do_test 4.5.44.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {2.00 1.00 3.00 2.00 4.00 3.00 2.00 1.50 3.00 2.50 4.00 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.45.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.45.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.46.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 2 3 3 4 4 3 3 4 4 5 5} + +do_test 4.5.46.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.50 2.50 3.50 3.50 4.50 2.00 3.00 3.00 4.00 4.00 5.00} + +do_execsql_test 4.5.47.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.47.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 2.00 2.00 3.00 3.00 4.00 1.50 2.00 2.50 3.00 3.50 4.00 2.00 2.00 3.00 3.00 4.00 4.00} + +do_execsql_test 4.5.48.1 { + SELECT max(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + min(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a +} {1 1 2 2 3 3 2 1 3 2 4 3 3 1 4 2 5 3} + +do_test 4.5.48.2 { + set myres {} + foreach r [db eval {SELECT avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + avg(c) OVER (PARTITION BY b ORDER BY b, a RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + FROM ttt ORDER BY a}] { + lappend myres [format %.2f [set r]] + } + set myres +} {1.00 1.00 2.00 2.00 3.00 3.00 1.50 1.50 2.50 2.50 3.50 3.50 2.00 2.00 3.00 3.00 4.00 4.00} + finish_test