mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Add support for new window functions related features - GROUPS frames, RANGE frames with logical start and end points, the EXCLUDE clause and window chaining.
FossilOrigin-Name: c6da39115d3e2b0fd3a03c4bcae8ee8b05a6bbd6b11f8c54712fbff6387f610d
This commit is contained in:
51
manifest
51
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\san\sobsolete\scomment\sin\sthe\sCLI.\s\sNo\scode\schanges.
|
||||
D 2019-03-25T22:05:22.540
|
||||
C Add\ssupport\sfor\snew\swindow\sfunctions\srelated\sfeatures\s-\sGROUPS\sframes,\sRANGE\sframes\swith\slogical\sstart\sand\send\spoints,\sthe\sEXCLUDE\sclause\sand\swindow\schaining.
|
||||
D 2019-03-26T13:08:34.839
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -457,7 +457,7 @@ F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
|
||||
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 6bea02598917ad9549d2d0c78bf8cc288eeb7a0b0f4298cbe1713db01340f9be
|
||||
F src/btree.c a644e8f3b71205e1e360ed5a28d8fc8feaa5c63fee3a49a36711ff83f4bdf6d2
|
||||
F src/btree.h 63b94fb38ce571c15eb6a3661815561b501d23d5948b2d1e951fbd7a2d04e8d3
|
||||
F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
|
||||
F src/build.c 7c8851893fb616115d7f6ae1e07df5076c6d4a8f592cd2affa04f3112176c38c
|
||||
@@ -505,7 +505,7 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b
|
||||
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
|
||||
F src/parse.y 741a270b7f2f85bc5d026d06fb5a9ccba5335304ff2831e1cb44b36cd0da6006
|
||||
F src/parse.y a020386af1739371b2eafba077497aacf2a840d1a178508dc6f8c19448e42054
|
||||
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
|
||||
@@ -514,14 +514,14 @@ F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
|
||||
F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3
|
||||
F src/printf.c 93a3d539019264683a444bc043c875e9a6cca43fe935ae7bf6cfff0af3bba118
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 09419ad5c432190b69be7c0c326e03abb548a97c2c50675b81b459e1b382d1d2
|
||||
F src/resolve.c f20cb5b953bd927e8c6b6e01662cce066a632b5d3a21d2938b93de0825aef5d5
|
||||
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
|
||||
F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49
|
||||
F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810
|
||||
F src/sqlite.h.in 633ca2147938402fe43118db929a7949dde3e2a08c138e40bbdec12a0e696129
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
|
||||
F src/sqliteInt.h f253c4ec15e577a293a462e5049f8ea1d0c7a31819b3a88acdd24698df8f4d0b
|
||||
F src/sqliteInt.h 19641f2402ef4e45fd2e222f5a45bb24e3f89a519059d35ce2819f46ce5e1a1e
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@@ -587,7 +587,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432
|
||||
F src/vacuum.c 532553ee1d47f69c1198858107b1f3af3d16af25f2ab4ce3b1263d9e333f26e2
|
||||
F src/vdbe.c f1e7b5320df80ff58c67176e35cb48062cbda2a9c9811f11db5faa48071d3fe4
|
||||
F src/vdbe.c 8f824b423460fbbd6a140f557b9d3cb26fa55404d03aee43584d11c7d1011b02
|
||||
F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
|
||||
F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f
|
||||
F src/vdbeapi.c 7a052df80d7e2e55382076174633e888f21fe200feb5d49b1b441b4c38ab851a
|
||||
@@ -605,7 +605,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
|
||||
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
|
||||
F src/wherecode.c 6fa4056c5ce019e4a8af33795906340176813cb3c1236f4b7b08df76a1b6287b
|
||||
F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c
|
||||
F src/window.c df2456386e0b1553a8d1fcf3a0ddc4c058fe2c650ea8c74b6bf8862082ddafc9
|
||||
F src/window.c 9849eee7e9e3e596f26cd84295d68ff501ccbc37287840fa07bc1717d6d09819
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -1197,8 +1197,8 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 52d2c37fe8cc07ec7362024c214b04bb69432995b3a984a3fbabc60fa6ada3ee
|
||||
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
|
||||
F test/permutations.test b8f0da2f53ef1bd7ff149a140ee625aa7276c94ae15eb9acc2d8ed4af8f22b13
|
||||
F test/pg_common.tcl 4740dc35190d6acdab14c097783331361301ab504a94d948f6afbb56ce0a51e8
|
||||
F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
|
||||
@@ -1677,16 +1677,22 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 53db04133c48065c7554cb7195b0d23b879feb2dc9dacf0945a259c423687133
|
||||
F test/window1.test 7484bf9a2ef2d845a50c9aff866efb8cd9d244b5916a9e97fb384e05f33d242b
|
||||
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
|
||||
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
|
||||
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
|
||||
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
|
||||
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
|
||||
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
|
||||
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
|
||||
F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb
|
||||
F test/window4.tcl 5fbaab489677914ee5686b2008426e336daf88a2f58be7df92757f780a5ebf91
|
||||
F test/window4.test bf8f86586ce101bf98e2306e597fa24aadc96c58d70ba4d11f956cf8ca4e0be3
|
||||
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
|
||||
F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
|
||||
F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b
|
||||
F test/window6.test 604890f2b0f976339e6a1774cd90d48840e57a54b4f21a8b4b3047aa2c9787d1
|
||||
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
|
||||
F test/window7.test ce7f865241fdd1c5c4db869cd7bb2986c3be836bc2e73649a6846dd920f63e0f
|
||||
F test/window8.tcl 97de3829e0e1aae2c3aaae41a55c54bc1b0751bbc80dfdd93020431b7a889dad
|
||||
F test/window8.test 0dd7e2d32605bf59dc6163b924faeff5951419c1c17a9e506e5a38606e97ab7e
|
||||
F test/windowerr.tcl 727d77959ac512b473dd2d659937f58688ce5460482a442c2d569fc8656491e5
|
||||
F test/windowerr.test 7962cf9b39f27b11ea5c62105ab2322a61ceac098dce536e2b8569c3053f62e7
|
||||
F test/windowfault.test cb27a4d8c85982733b123af667921df3a96e23d3739b15d414de75054b334cbe
|
||||
F test/with1.test a07b5aad7f77acdf13e52e8814ea94606fcc72e9ea4c99baf293e9d7c63940be
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test 8d26920c88283e0a473ceebd3451554922108ce7b2a6a1157c47eb0a7011212c
|
||||
@@ -1735,7 +1741,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
|
||||
F tool/mkkeywordhash.c 1f7f2ac1d9f262c08b67faaca47e6a68262ff39113fa4b27d1db2843b4c33e73
|
||||
F tool/mkkeywordhash.c 127d0b86eea32a461b79b6c6b11fa5fd223787b681156d682bf1824bb20e2494
|
||||
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
|
||||
@@ -1807,7 +1813,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P e775ef002dd33e6bcbeec8d4b6ad7f59749e35548c7a59c9fa3bcfdc5cc50730
|
||||
R 3d12cfa0cda4f35a3d1533c43ce31db3
|
||||
U drh
|
||||
Z b5e63031019719c1b59c8c1822668f3c
|
||||
P fade103cbac1b067f9544935b767f36dc266aceb3269cc84a3ae3b04ad9a4823 9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
|
||||
R bdc22793cb51647fca24f70e83877204
|
||||
T +closed 9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
|
||||
U dan
|
||||
Z 8d3e4b02d8e1dd0a57c5b612deb65ffe
|
||||
|
@@ -1 +1 @@
|
||||
fade103cbac1b067f9544935b767f36dc266aceb3269cc84a3ae3b04ad9a4823
|
||||
c6da39115d3e2b0fd3a03c4bcae8ee8b05a6bbd6b11f8c54712fbff6387f610d
|
@@ -8834,9 +8834,12 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
assert( pCur->curFlags & BTCF_WriteFlag );
|
||||
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
||||
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
|
||||
assert( pCur->ix<pCur->pPage->nCell );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
|
||||
if( pCur->eState==CURSOR_REQUIRESEEK ){
|
||||
rc = btreeRestoreCursorPosition(pCur);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
|
||||
iCellDepth = pCur->iPage;
|
||||
iCellIdx = pCur->ix;
|
||||
|
54
src/parse.y
54
src/parse.y
@@ -218,6 +218,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
|
||||
%endif SQLITE_OMIT_COMPOUND_SELECT
|
||||
%ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
|
||||
EXCLUDE GROUPS OTHERS TIES
|
||||
%endif SQLITE_OMIT_WINDOWFUNC
|
||||
REINDEX RENAME CTIME_KW IF
|
||||
.
|
||||
@@ -1633,13 +1634,14 @@ wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
|
||||
windowdefn_list(A) ::= windowdefn(Z). { A = Z; }
|
||||
windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). {
|
||||
assert( Z!=0 );
|
||||
sqlite3WindowChain(pParse, Z, Y);
|
||||
Z->pNextWin = Y;
|
||||
A = Z;
|
||||
}
|
||||
|
||||
%type windowdefn {Window*}
|
||||
%destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);}
|
||||
windowdefn(A) ::= nm(X) AS window(Y). {
|
||||
windowdefn(A) ::= nm(X) AS LP window(Y) RP. {
|
||||
if( ALWAYS(Y) ){
|
||||
Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n);
|
||||
}
|
||||
@@ -1667,29 +1669,38 @@ windowdefn(A) ::= nm(X) AS window(Y). {
|
||||
%type frame_bound_e {struct FrameBound}
|
||||
%destructor frame_bound_e {sqlite3ExprDelete(pParse->db, $$.pExpr);}
|
||||
|
||||
window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. {
|
||||
A = Z;
|
||||
if( ALWAYS(A) ){
|
||||
A->pPartition = X;
|
||||
A->pOrderBy = Y;
|
||||
}
|
||||
window(A) ::= PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, X, Y, 0);
|
||||
}
|
||||
window(A) ::= nm(W) PARTITION BY nexprlist(X) orderby_opt(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, X, Y, &W);
|
||||
}
|
||||
window(A) ::= ORDER BY sortlist(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, Y, 0);
|
||||
}
|
||||
window(A) ::= nm(W) ORDER BY sortlist(Y) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, Y, &W);
|
||||
}
|
||||
window(A) ::= frame_opt(Z). {
|
||||
A = Z;
|
||||
}
|
||||
window(A) ::= nm(W) frame_opt(Z). {
|
||||
A = sqlite3WindowAssemble(pParse, Z, 0, 0, &W);
|
||||
}
|
||||
|
||||
part_opt(A) ::= PARTITION BY nexprlist(X). { A = X; }
|
||||
part_opt(A) ::= . { A = 0; }
|
||||
|
||||
frame_opt(A) ::= . {
|
||||
A = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0);
|
||||
A = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
|
||||
}
|
||||
frame_opt(A) ::= range_or_rows(X) frame_bound_s(Y). {
|
||||
A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0);
|
||||
frame_opt(A) ::= range_or_rows(X) frame_bound_s(Y) frame_exclude_opt(Z). {
|
||||
A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, TK_CURRENT, 0, Z);
|
||||
}
|
||||
frame_opt(A) ::= range_or_rows(X) BETWEEN frame_bound_s(Y) AND frame_bound_e(Z). {
|
||||
A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, Z.eType, Z.pExpr);
|
||||
frame_opt(A) ::= range_or_rows(X) BETWEEN frame_bound_s(Y) AND frame_bound_e(Z) frame_exclude_opt(W). {
|
||||
A = sqlite3WindowAlloc(pParse, X, Y.eType, Y.pExpr, Z.eType, Z.pExpr, W);
|
||||
}
|
||||
|
||||
range_or_rows(A) ::= RANGE. { A = TK_RANGE; }
|
||||
range_or_rows(A) ::= ROWS. { A = TK_ROWS; }
|
||||
range_or_rows(A) ::= GROUPS. { A = TK_GROUPS;}
|
||||
|
||||
|
||||
frame_bound_s(A) ::= frame_bound(X). { A = X; }
|
||||
@@ -1701,13 +1712,24 @@ frame_bound(A) ::= expr(X) PRECEDING. { A.eType = TK_PRECEDING; A.pExpr = X; }
|
||||
frame_bound(A) ::= CURRENT ROW. { A.eType = TK_CURRENT ; A.pExpr = 0; }
|
||||
frame_bound(A) ::= expr(X) FOLLOWING. { A.eType = TK_FOLLOWING; A.pExpr = X; }
|
||||
|
||||
%type frame_exclude_opt {u8}
|
||||
frame_exclude_opt(A) ::= . { A = 0; }
|
||||
frame_exclude_opt(A) ::= EXCLUDE frame_exclude(X). { A = X; }
|
||||
|
||||
%type frame_exclude {u8}
|
||||
frame_exclude(A) ::= NO OTHERS. { A = 0; }
|
||||
frame_exclude(A) ::= CURRENT ROW. { A = TK_CURRENT; }
|
||||
frame_exclude(A) ::= GROUP. { A = TK_GROUP; }
|
||||
frame_exclude(A) ::= TIES. { A = TK_TIES; }
|
||||
|
||||
|
||||
%type window_clause {Window*}
|
||||
%destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);}
|
||||
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
|
||||
|
||||
%type over_clause {Window*}
|
||||
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}
|
||||
over_clause(A) ::= filter_opt(W) OVER window(Z). {
|
||||
over_clause(A) ::= filter_opt(W) OVER LP window(Z) RP. {
|
||||
A = Z;
|
||||
assert( A!=0 );
|
||||
A->pFilter = W;
|
||||
|
@@ -1424,7 +1424,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
*/
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
struct SrcList_item *pItem = &p->pSrc->a[i];
|
||||
if( pItem->pSelect ){
|
||||
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
|
||||
NameContext *pNC; /* Used to iterate name contexts */
|
||||
int nRef = 0; /* Refcount for pOuterNC and outer contexts */
|
||||
const char *zSavedContext = pParse->zAuthContext;
|
||||
|
@@ -1691,7 +1691,6 @@ 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 0x00010000 /* Built-in window-only function */
|
||||
#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
|
||||
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
|
||||
|
||||
/*
|
||||
@@ -3555,11 +3554,14 @@ struct TreeView {
|
||||
*/
|
||||
struct Window {
|
||||
char *zName; /* Name of window (may be NULL) */
|
||||
char *zBase; /* Name of base window for chaining (may be NULL) */
|
||||
ExprList *pPartition; /* PARTITION BY clause */
|
||||
ExprList *pOrderBy; /* ORDER BY clause */
|
||||
u8 eType; /* TK_RANGE or TK_ROWS */
|
||||
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
||||
u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
||||
u8 bImplicitFrame; /* True if frame was implicitly specified */
|
||||
u8 eExclude;
|
||||
Expr *pStart; /* Expression for "<expr> PRECEDING" */
|
||||
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
|
||||
Window *pNextWin; /* Next window function belonging to this SELECT */
|
||||
@@ -3570,17 +3572,19 @@ struct Window {
|
||||
int regResult;
|
||||
int csrApp; /* Function cursor (used by min/max) */
|
||||
int regApp; /* Function register (also used by min/max) */
|
||||
int regPart; /* First in a set of registers holding PARTITION BY
|
||||
** and ORDER BY values for the window */
|
||||
int regPart; /* Array of registers for PARTITION BY values */
|
||||
Expr *pOwner; /* Expression object this window is attached to */
|
||||
int nBufferCol; /* Number of columns in buffer table */
|
||||
int iArgCol; /* Offset of first argument for this function */
|
||||
int regOne; /* Register containing constant value 1 */
|
||||
int regStartRowid;
|
||||
int regEndRowid;
|
||||
};
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
void sqlite3WindowDelete(sqlite3*, Window*);
|
||||
void sqlite3WindowListDelete(sqlite3 *db, Window *p);
|
||||
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
|
||||
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
|
||||
void sqlite3WindowAttach(Parse*, Expr*, Window*);
|
||||
int sqlite3WindowCompare(Parse*, Window*, Window*);
|
||||
void sqlite3WindowCodeInit(Parse*, Window*);
|
||||
@@ -3591,6 +3595,8 @@ void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
|
||||
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
|
||||
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
|
||||
void sqlite3WindowFunctions(void);
|
||||
void sqlite3WindowChain(Parse*, Window*, Window*);
|
||||
Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
||||
#else
|
||||
# define sqlite3WindowDelete(a,b)
|
||||
# define sqlite3WindowFunctions()
|
||||
|
@@ -1918,7 +1918,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
** OP_Eq or OP_Ne) then take the jump or not depending on whether
|
||||
** or not both operands are null.
|
||||
*/
|
||||
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
|
||||
assert( (flags1 & MEM_Cleared)==0 );
|
||||
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
|
||||
testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 );
|
||||
@@ -1927,7 +1926,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
){
|
||||
res = 0; /* Operands are equal */
|
||||
}else{
|
||||
res = 1; /* Operands are not equal */
|
||||
res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
|
||||
}
|
||||
}else{
|
||||
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
|
||||
@@ -3606,6 +3605,7 @@ case OP_OpenDup: {
|
||||
pCx->pKeyInfo = pOrig->pKeyInfo;
|
||||
pCx->isTable = pOrig->isTable;
|
||||
pCx->pgnoRoot = pOrig->pgnoRoot;
|
||||
pCx->isOrdered = pOrig->isOrdered;
|
||||
rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
|
||||
pCx->pKeyInfo, pCx->uc.pCursor);
|
||||
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
|
||||
@@ -6534,6 +6534,7 @@ case OP_AggFinal: {
|
||||
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( pOp->p3 ){
|
||||
memAboutToChange(p, &aMem[pOp->p3]);
|
||||
rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc);
|
||||
pMem = &aMem[pOp->p3];
|
||||
}else
|
||||
|
2393
src/window.c
2393
src/window.c
File diff suppressed because it is too large
Load Diff
@@ -1032,13 +1032,15 @@ test_suite "rbu" -description {
|
||||
test_suite "no_optimization" -description {
|
||||
Run test scripts with optimizations disabled using the
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface.
|
||||
} -files {
|
||||
where.test where2.test where3.test where4.test where5.test
|
||||
where6.test where7.test where8.test where9.test
|
||||
whereA.test whereB.test wherelimit.test
|
||||
select1.test select2.test select3.test select4.test select5.test
|
||||
select7.test select8.test selectA.test selectC.test
|
||||
} -dbconfig {
|
||||
} -files [
|
||||
test_set \
|
||||
[glob -nocomplain $::testdir/window*.test] \
|
||||
where.test where2.test where3.test where4.test where5.test \
|
||||
where6.test where7.test where8.test where9.test \
|
||||
whereA.test whereB.test wherelimit.test \
|
||||
select1.test select2.test select3.test select4.test select5.test \
|
||||
select7.test select8.test selectA.test selectC.test
|
||||
] -dbconfig {
|
||||
optimization_control $::dbhandle all 0
|
||||
}
|
||||
|
||||
|
@@ -40,17 +40,26 @@ proc execsql {sql} {
|
||||
#puts $lSql
|
||||
|
||||
set ret ""
|
||||
set nChar 0
|
||||
foreach stmt $lSql {
|
||||
set res [pg_exec $::db $stmt]
|
||||
set err [pg_result $res -error]
|
||||
if {$err!=""} { error $err }
|
||||
|
||||
for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} {
|
||||
if {$i==0} {
|
||||
set ret [pg_result $res -getTuple 0]
|
||||
set t [pg_result $res -getTuple $i]
|
||||
set nNew [string length $t]
|
||||
if {$nChar>0 && ($nChar+$nNew+3)>75} {
|
||||
append ret "\n "
|
||||
set nChar 0
|
||||
} else {
|
||||
append ret " [pg_result $res -getTuple $i]"
|
||||
if {$nChar>0} {
|
||||
append ret " "
|
||||
incr nChar 3
|
||||
}
|
||||
}
|
||||
# lappend ret {*}[pg_result $res -getTuple $i]
|
||||
incr nChar $nNew
|
||||
append ret $t
|
||||
}
|
||||
pg_result $res -clear
|
||||
}
|
||||
@@ -61,12 +70,28 @@ proc execsql {sql} {
|
||||
proc execsql_test {tn sql} {
|
||||
set res [execsql $sql]
|
||||
set sql [string map {string_agg group_concat} $sql]
|
||||
set sql [string map [list {NULLS FIRST} {}] $sql]
|
||||
set sql [string map [list {NULLS LAST} {}] $sql]
|
||||
puts $::fd "do_execsql_test $tn {"
|
||||
puts $::fd " [string trim $sql]"
|
||||
puts $::fd "} {$res}"
|
||||
puts $::fd ""
|
||||
}
|
||||
|
||||
proc errorsql_test {tn sql} {
|
||||
set rc [catch {execsql $sql} msg]
|
||||
if {$rc==0} {
|
||||
error "errorsql_test SQL did not cause an error!"
|
||||
}
|
||||
set msg [lindex [split [string trim $msg] "\n"] 0]
|
||||
puts $::fd "# PG says $msg"
|
||||
set sql [string map {string_agg group_concat} $sql]
|
||||
puts $::fd "do_test $tn { catch { execsql {"
|
||||
puts $::fd " [string trim $sql]"
|
||||
puts $::fd "} } } 1"
|
||||
puts $::fd ""
|
||||
}
|
||||
|
||||
# Same as [execsql_test], except coerce all results to floating point values
|
||||
# with two decimal points.
|
||||
#
|
||||
@@ -88,10 +113,12 @@ do_test $tn {
|
||||
lappend myres [format $F [set r]]
|
||||
}
|
||||
set res2 {$res2}
|
||||
set i 0
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-$T) || [set r]>([set r2]+$T)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
incr i
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
@@ -720,10 +720,299 @@ do_execsql_test 17.3 {
|
||||
ORDER BY 10+sum(a) OVER (ORDER BY a) DESC;
|
||||
} {16 13 11}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test error cases from chaining window definitions.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 18.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);
|
||||
INSERT INTO t1 VALUES(1, 'odd', 'one', 1);
|
||||
INSERT INTO t1 VALUES(2, 'even', 'two', 2);
|
||||
INSERT INTO t1 VALUES(3, 'odd', 'three', 3);
|
||||
INSERT INTO t1 VALUES(4, 'even', 'four', 4);
|
||||
INSERT INTO t1 VALUES(5, 'odd', 'five', 5);
|
||||
INSERT INTO t1 VALUES(6, 'even', 'six', 6);
|
||||
}
|
||||
|
||||
foreach {tn sql error} {
|
||||
1 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
||||
win2 AS (win1 ORDER BY b)
|
||||
} {cannot override frame specification of window: win1}
|
||||
|
||||
2 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (),
|
||||
win2 AS (win4 ORDER BY b)
|
||||
} {no such window: win4}
|
||||
|
||||
3 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (),
|
||||
win2 AS (win1 PARTITION BY d)
|
||||
} {cannot override PARTITION clause of window: win1}
|
||||
|
||||
4 {
|
||||
SELECT c, sum(d) OVER win2 FROM t1
|
||||
WINDOW win1 AS (ORDER BY b),
|
||||
win2 AS (win1 ORDER BY d)
|
||||
} {cannot override ORDER BY clause of window: win1}
|
||||
} {
|
||||
do_catchsql_test 18.1.$tn $sql [list 1 $error]
|
||||
}
|
||||
|
||||
foreach {tn sql error} {
|
||||
1 {
|
||||
SELECT c, sum(d) OVER (win1 ORDER BY b) FROM t1
|
||||
WINDOW win1 AS (ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
||||
} {cannot override frame specification of window: win1}
|
||||
|
||||
2 {
|
||||
SELECT c, sum(d) OVER (win4 ORDER BY b) FROM t1
|
||||
WINDOW win1 AS ()
|
||||
} {no such window: win4}
|
||||
|
||||
3 {
|
||||
SELECT c, sum(d) OVER (win1 PARTITION BY d) FROM t1
|
||||
WINDOW win1 AS ()
|
||||
} {cannot override PARTITION clause of window: win1}
|
||||
|
||||
4 {
|
||||
SELECT c, sum(d) OVER (win1 ORDER BY d) FROM t1
|
||||
WINDOW win1 AS (ORDER BY b)
|
||||
} {cannot override ORDER BY clause of window: win1}
|
||||
} {
|
||||
do_catchsql_test 18.2.$tn $sql [list 1 $error]
|
||||
}
|
||||
|
||||
do_execsql_test 18.3.1 {
|
||||
SELECT group_concat(c, '.') OVER (PARTITION BY b ORDER BY c)
|
||||
FROM t1
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 18.3.2 {
|
||||
SELECT group_concat(c, '.') OVER (win1 ORDER BY c)
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 18.3.3 {
|
||||
SELECT group_concat(c, '.') OVER win2
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 18.3.4 {
|
||||
SELECT group_concat(c, '.') OVER (win2)
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
do_execsql_test 18.3.5 {
|
||||
SELECT group_concat(c, '.') OVER win5
|
||||
FROM t1
|
||||
WINDOW win1 AS (PARTITION BY b),
|
||||
win2 AS (win1),
|
||||
win3 AS (win2),
|
||||
win4 AS (win3),
|
||||
win5 AS (win4 ORDER BY c)
|
||||
} {four four.six four.six.two five five.one five.one.three}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test RANGE <expr> PRECEDING/FOLLOWING when there are string, blob
|
||||
# and NULL values in the dataset.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 19.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES
|
||||
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
|
||||
('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
|
||||
}
|
||||
do_execsql_test 19.1 {
|
||||
SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
|
||||
} {1 1 2 3 3 6 4 10 5 15 a 21 b 28 c 36 d 45 e 55}
|
||||
|
||||
do_execsql_test 19.2.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1;
|
||||
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
|
||||
do_execsql_test 19.2.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY a ASC;
|
||||
} {1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
|
||||
|
||||
do_execsql_test 19.3.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1;
|
||||
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
|
||||
do_execsql_test 19.3.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t1 ORDER BY a ASC;
|
||||
} {1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
|
||||
|
||||
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES
|
||||
(NULL, 100), (NULL, 100),
|
||||
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5),
|
||||
('a', 6), ('b', 7), ('c', 8), ('d', 9), ('e', 10);
|
||||
}
|
||||
do_execsql_test 20.1 {
|
||||
SELECT a, sum(b) OVER (ORDER BY a) FROM t1;
|
||||
} {
|
||||
{} 200 {} 200 1 201 2 203 3 206 4 210 5 215
|
||||
a 221 b 228 c 236 d 245 e 255
|
||||
}
|
||||
|
||||
do_execsql_test 20.2.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1;
|
||||
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
|
||||
do_execsql_test 20.2.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY a ASC;
|
||||
} {{} 200 {} 200 1 3 2 6 3 9 4 12 5 9 a 6 b 7 c 8 d 9 e 10}
|
||||
|
||||
do_execsql_test 20.3.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1;
|
||||
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
|
||||
do_execsql_test 20.3.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t1 ORDER BY a ASC;
|
||||
} {{} 200 {} 200 1 3 2 6 3 10 4 14 5 12 a 6 b 7 c 8 d 9 e 10}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 21.0 {
|
||||
CREATE TABLE keyword_tab(
|
||||
current, exclude, filter, following, groups, no, others, over,
|
||||
partition, preceding, range, ties, unbounded, window
|
||||
);
|
||||
}
|
||||
do_execsql_test 21.1 {
|
||||
SELECT
|
||||
current, exclude, filter, following, groups, no, others, over,
|
||||
partition, preceding, range, ties, unbounded, window
|
||||
FROM keyword_tab
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
foreach {tn expr err} {
|
||||
1 4.5 0
|
||||
2 NULL 1
|
||||
3 0.0 0
|
||||
4 0.1 0
|
||||
5 -0.1 1
|
||||
6 '' 1
|
||||
7 '2.0' 0
|
||||
8 '2.0x' 1
|
||||
9 x'1234' 1
|
||||
10 '1.2' 0
|
||||
} {
|
||||
set res {0 1}
|
||||
if {$err} {set res {1 {frame starting offset must be a non-negative number}} }
|
||||
do_catchsql_test 22.$tn.1 "
|
||||
WITH a(x, y) AS ( VALUES(1, 2) )
|
||||
SELECT sum(x) OVER (
|
||||
ORDER BY y RANGE BETWEEN $expr PRECEDING AND UNBOUNDED FOLLOWING
|
||||
) FROM a
|
||||
" $res
|
||||
|
||||
set res {0 1}
|
||||
if {$err} {set res {1 {frame ending offset must be a non-negative number}} }
|
||||
do_catchsql_test 22.$tn.2 "
|
||||
WITH a(x, y) AS ( VALUES(1, 2) )
|
||||
SELECT sum(x) OVER (
|
||||
ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND $expr FOLLOWING
|
||||
) FROM a
|
||||
" $res
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 23.0 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
CREATE INDEX t5ab ON t5(a, b);
|
||||
}
|
||||
|
||||
proc do_ordercount_test {tn sql nOrderBy} {
|
||||
set plan [execsql "EXPLAIN QUERY PLAN $sql"]
|
||||
uplevel [list do_test $tn [list regexp -all ORDER $plan] $nOrderBy]
|
||||
}
|
||||
|
||||
do_ordercount_test 23.1 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY a, b),
|
||||
sum(c) OVER (PARTITION BY a ORDER BY b)
|
||||
FROM t5
|
||||
} 0
|
||||
|
||||
do_ordercount_test 23.2 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY b, a),
|
||||
sum(c) OVER (PARTITION BY b ORDER BY a)
|
||||
FROM t5
|
||||
} 1
|
||||
|
||||
do_ordercount_test 23.3 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY b, a),
|
||||
sum(c) OVER (ORDER BY c, b)
|
||||
FROM t5
|
||||
} 2
|
||||
|
||||
do_ordercount_test 23.4 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
|
||||
sum(c) OVER (ORDER BY b RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
|
||||
sum(c) OVER (ORDER BY b GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
|
||||
FROM t5
|
||||
} 1
|
||||
|
||||
do_ordercount_test 23.5 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY b+1 ROWS UNBOUNDED PRECEDING),
|
||||
sum(c) OVER (ORDER BY b+1 RANGE UNBOUNDED PRECEDING),
|
||||
sum(c) OVER (ORDER BY b+1 GROUPS UNBOUNDED PRECEDING)
|
||||
FROM t5
|
||||
} 1
|
||||
|
||||
do_ordercount_test 23.6 {
|
||||
SELECT
|
||||
sum(c) OVER (ORDER BY b+1 ROWS UNBOUNDED PRECEDING),
|
||||
sum(c) OVER (ORDER BY b+2 RANGE UNBOUNDED PRECEDING),
|
||||
sum(c) OVER (ORDER BY b+3 GROUPS UNBOUNDED PRECEDING)
|
||||
FROM t5
|
||||
} 3
|
||||
|
||||
do_execsql_test 24.1 {
|
||||
SELECT sum(44) OVER ()
|
||||
} {44}
|
||||
|
||||
do_execsql_test 24.2 {
|
||||
SELECT lead(44) OVER ()
|
||||
} {{}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 25.0 {
|
||||
CREATE TABLE t1 ( t1_id INTEGER PRIMARY KEY );
|
||||
CREATE TABLE t2 ( t2_id INTEGER PRIMARY KEY );
|
||||
CREATE TABLE t3 ( t3_id INTEGER PRIMARY KEY );
|
||||
@@ -733,19 +1022,53 @@ do_execsql_test 18.0 {
|
||||
INSERT INTO t3 VALUES(10), (11), (12);
|
||||
}
|
||||
|
||||
do_execsql_test 18.1 {
|
||||
do_execsql_test 25.1 {
|
||||
SELECT t1.* FROM t1, t2 WHERE
|
||||
t1_id=t2_id AND t1_id IN (
|
||||
SELECT t1_id + row_number() OVER ( ORDER BY t1_id ) FROM t3
|
||||
)
|
||||
}
|
||||
|
||||
do_execsql_test 18.2 {
|
||||
do_execsql_test 25.2 {
|
||||
SELECT t1.* FROM t1, t2 WHERE
|
||||
t1_id=t2_id AND t1_id IN (
|
||||
SELECT row_number() OVER ( ORDER BY t1_id ) FROM t3
|
||||
)
|
||||
} {3}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 26.0 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(c);
|
||||
}
|
||||
|
||||
do_execsql_test 26.1 {
|
||||
SELECT ( SELECT row_number() OVER () FROM ( SELECT c FROM t1 ) ) FROM t2
|
||||
} {}
|
||||
|
||||
do_execsql_test 26.2 {
|
||||
INSERT INTO t1 VALUES(1), (2), (3), (4);
|
||||
INSERT INTO t2 VALUES(2), (6), (8), (4);
|
||||
SELECT c, c IN (
|
||||
SELECT row_number() OVER () FROM ( SELECT c FROM t1 )
|
||||
) FROM t2
|
||||
} {2 1 6 0 8 0 4 1}
|
||||
|
||||
do_execsql_test 26.3 {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
|
||||
INSERT INTO t2 VALUES(1), (2), (3), (4);
|
||||
INSERT INTO t1 VALUES(1), (1), (2), (3), (3), (3), (3), (4), (4);
|
||||
|
||||
SELECT c, c IN (
|
||||
SELECT row_number() OVER () FROM ( SELECT 1 FROM t1 WHERE x=c )
|
||||
) FROM t2
|
||||
} {1 1 2 0 3 1 4 0}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
@@ -21,7 +21,6 @@ execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);
|
||||
INSERT INTO t2(a, b) VALUES
|
||||
(1,0), (2,74), (3,41), (4,74), (5,23), (6,99), (7,26), (8,33), (9,2),
|
||||
(10,89), (11,81), (12,96), (13,59), (14,38), (15,68), (16,39), (17,62),
|
||||
(18,91), (19,46), (20,6), (21,99), (22,97), (23,27), (24,46), (25,78),
|
||||
(26,54), (27,97), (28,8), (29,67), (30,29), (31,93), (32,84), (33,77),
|
||||
@@ -73,6 +72,11 @@ foreach {tn window} {
|
||||
15 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING"
|
||||
16 "ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING"
|
||||
17 "ROWS BETWEEN 4 FOLLOWING AND UNBOUNDED FOLLOWING"
|
||||
|
||||
18 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW"
|
||||
19 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES"
|
||||
20 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP"
|
||||
|
||||
} {
|
||||
execsql_test 1.$tn.2.1 "SELECT max(b) OVER ( ORDER BY a $window ) FROM t2"
|
||||
execsql_test 1.$tn.2.2 "SELECT min(b) OVER ( ORDER BY a $window ) FROM t2"
|
||||
@@ -307,6 +311,28 @@ foreach {tn window} {
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.7 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 ORDER BY b%10 $window)
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.8 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER (win1 $window)
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.14.9 "
|
||||
SELECT string_agg(CAST(b AS TEXT), '.') OVER win2
|
||||
FROM t2
|
||||
WINDOW win1 AS (PARTITION BY b%2,a ORDER BY b%10),
|
||||
win2 AS (win1 $window)
|
||||
ORDER BY 1
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.15.1 "
|
||||
SELECT count(*) OVER win, string_agg(CAST(b AS TEXT), '.')
|
||||
FILTER (WHERE a%2=0) OVER win FROM t2
|
||||
|
34183
test/window3.test
34183
test/window3.test
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
# 2018 May 19
|
||||
## 2018 May 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
|
@@ -150,7 +150,8 @@ do_execsql_test 2.4.1 {
|
||||
SELECT group_concat(b, '.') OVER (
|
||||
ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
|
||||
) FROM t4
|
||||
} {A.B.C.D.E.F.G.H.I.J B.C.D.E.F.G.H.I.J C.D.E.F.G.H.I.J D.E.F.G.H.I.J E.F.G.H.I.J F.G.H.I.J G.H.I.J H.I.J I.J J}
|
||||
} {A.B.C.D.E.F.G.H.I.J B.C.D.E.F.G.H.I.J C.D.E.F.G.H.I.J D.E.F.G.H.I.J
|
||||
E.F.G.H.I.J F.G.H.I.J G.H.I.J H.I.J I.J J}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
DROP TABLE IF EXISTS t5;
|
||||
@@ -1224,10 +1225,12 @@ do_test 9.3 {
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set res2 {1.0000 0.0000 1.0000 0.0000 1.0000 0.0000 4.0000 0.0000 4.0000 0.0000 6.0000 0.0000 7.0000 0.0000}
|
||||
set i 0
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
incr i
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
@@ -1247,10 +1250,12 @@ do_test 9.6 {
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set res2 {0.0000 0.0000 0.0000}
|
||||
set i 0
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
incr i
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
@@ -1262,10 +1267,12 @@ do_test 9.7 {
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set res2 {1.0000 1.0000 1.0000}
|
||||
set i 0
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
incr i
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
@@ -219,17 +219,17 @@ do_execsql_test 9.0 {
|
||||
} {
|
||||
1 1 2 1,2 3 1,2,3 4 2,3,4 5 3,4,5
|
||||
}
|
||||
do_catchsql_test 9.1 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
|
||||
SELECT x, group_concat(x) OVER (ORDER BY x RANGE 2 PRECEDING)
|
||||
FROM c;
|
||||
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
|
||||
|
||||
do_catchsql_test 9.2 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
|
||||
SELECT x, group_concat(x) OVER (ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING)
|
||||
FROM c;
|
||||
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
|
||||
#do_catchsql_test 9.1 {
|
||||
# WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
|
||||
# SELECT x, group_concat(x) OVER (ORDER BY x RANGE 2 PRECEDING)
|
||||
# FROM c;
|
||||
#} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
|
||||
#
|
||||
#do_catchsql_test 9.2 {
|
||||
# WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
|
||||
# SELECT x, group_concat(x) OVER (ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING)
|
||||
# FROM c;
|
||||
#} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
|
||||
|
||||
do_catchsql_test 9.3 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
|
||||
@@ -262,7 +262,7 @@ foreach {tn frame} {
|
||||
SELECT count() OVER (
|
||||
ORDER BY x ROWS $frame
|
||||
) FROM c;
|
||||
" {1 {unsupported frame delimiter for ROWS}}
|
||||
" {1 {unsupported frame specification}}
|
||||
}
|
||||
|
||||
do_catchsql_test 9.8.1 {
|
||||
|
91
test/window7.tcl
Normal file
91
test/window7.tcl
Normal file
@@ -0,0 +1,91 @@
|
||||
# 2018 May 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname $argv0] pg_common.tcl]
|
||||
|
||||
#=========================================================================
|
||||
|
||||
start_test window7 "2019 March 01"
|
||||
ifcapable !windowfunc
|
||||
|
||||
execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t3(a INTEGER, b INTEGER);
|
||||
INSERT INTO t3 VALUES
|
||||
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8),
|
||||
(9, 9), (0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16),
|
||||
(7, 17), (8, 18), (9, 19), (0, 20), (1, 21), (2, 22), (3, 23), (4, 24),
|
||||
(5, 25), (6, 26), (7, 27), (8, 28), (9, 29), (0, 30), (1, 31), (2, 32),
|
||||
(3, 33), (4, 34), (5, 35), (6, 36), (7, 37), (8, 38), (9, 39), (0, 40),
|
||||
(1, 41), (2, 42), (3, 43), (4, 44), (5, 45), (6, 46), (7, 47), (8, 48),
|
||||
(9, 49), (0, 50), (1, 51), (2, 52), (3, 53), (4, 54), (5, 55), (6, 56),
|
||||
(7, 57), (8, 58), (9, 59), (0, 60), (1, 61), (2, 62), (3, 63), (4, 64),
|
||||
(5, 65), (6, 66), (7, 67), (8, 68), (9, 69), (0, 70), (1, 71), (2, 72),
|
||||
(3, 73), (4, 74), (5, 75), (6, 76), (7, 77), (8, 78), (9, 79), (0, 80),
|
||||
(1, 81), (2, 82), (3, 83), (4, 84), (5, 85), (6, 86), (7, 87), (8, 88),
|
||||
(9, 89), (0, 90), (1, 91), (2, 92), (3, 93), (4, 94), (5, 95), (6, 96),
|
||||
(7, 97), (8, 98), (9, 99), (0, 100);
|
||||
}
|
||||
|
||||
execsql_test 1.1 {
|
||||
SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.3 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.4 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.5 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.6 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.7 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 1.8.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
execsql_test 1.8.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
94
test/window7.test
Normal file
94
test/window7.test
Normal file
@@ -0,0 +1,94 @@
|
||||
# 2019 March 01
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
####################################################
|
||||
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
|
||||
####################################################
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix window7
|
||||
|
||||
ifcapable !windowfunc { finish_test ; return }
|
||||
do_execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t3(a INTEGER, b INTEGER);
|
||||
INSERT INTO t3 VALUES
|
||||
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8),
|
||||
(9, 9), (0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16),
|
||||
(7, 17), (8, 18), (9, 19), (0, 20), (1, 21), (2, 22), (3, 23), (4, 24),
|
||||
(5, 25), (6, 26), (7, 27), (8, 28), (9, 29), (0, 30), (1, 31), (2, 32),
|
||||
(3, 33), (4, 34), (5, 35), (6, 36), (7, 37), (8, 38), (9, 39), (0, 40),
|
||||
(1, 41), (2, 42), (3, 43), (4, 44), (5, 45), (6, 46), (7, 47), (8, 48),
|
||||
(9, 49), (0, 50), (1, 51), (2, 52), (3, 53), (4, 54), (5, 55), (6, 56),
|
||||
(7, 57), (8, 58), (9, 59), (0, 60), (1, 61), (2, 62), (3, 63), (4, 64),
|
||||
(5, 65), (6, 66), (7, 67), (8, 68), (9, 69), (0, 70), (1, 71), (2, 72),
|
||||
(3, 73), (4, 74), (5, 75), (6, 76), (7, 77), (8, 78), (9, 79), (0, 80),
|
||||
(1, 81), (2, 82), (3, 83), (4, 84), (5, 85), (6, 86), (7, 87), (8, 88),
|
||||
(9, 89), (0, 90), (1, 91), (2, 92), (3, 93), (4, 94), (5, 95), (6, 96),
|
||||
(7, 97), (8, 98), (9, 99), (0, 100);
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1;
|
||||
} {0 550 1 460 2 470 3 480 4 490 5 500 6 510 7 520 8 530 9 540}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590}
|
||||
|
||||
do_execsql_test 1.8.1 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540}
|
||||
|
||||
do_execsql_test 1.8.2 {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t3 ORDER BY 1;
|
||||
} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070}
|
||||
|
||||
finish_test
|
274
test/window8.tcl
Normal file
274
test/window8.tcl
Normal file
@@ -0,0 +1,274 @@
|
||||
# 2018 May 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname $argv0] pg_common.tcl]
|
||||
|
||||
#=========================================================================
|
||||
|
||||
start_test window8 "2019 March 01"
|
||||
ifcapable !windowfunc
|
||||
|
||||
execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t3(a TEXT, b TEXT, c INTEGER);
|
||||
INSERT INTO t3 VALUES
|
||||
('HH', 'bb', 355), ('CC', 'aa', 158), ('BB', 'aa', 399),
|
||||
('FF', 'bb', 938), ('HH', 'aa', 480), ('FF', 'bb', 870),
|
||||
('JJ', 'aa', 768), ('JJ', 'aa', 899), ('GG', 'bb', 929),
|
||||
('II', 'bb', 421), ('GG', 'bb', 844), ('FF', 'bb', 574),
|
||||
('CC', 'bb', 822), ('GG', 'bb', 938), ('BB', 'aa', 660),
|
||||
('HH', 'aa', 979), ('BB', 'bb', 792), ('DD', 'aa', 845),
|
||||
('JJ', 'bb', 354), ('FF', 'bb', 295), ('JJ', 'aa', 234),
|
||||
('BB', 'bb', 840), ('AA', 'aa', 934), ('EE', 'aa', 113),
|
||||
('AA', 'bb', 309), ('BB', 'aa', 412), ('AA', 'aa', 911),
|
||||
('AA', 'bb', 572), ('II', 'aa', 398), ('II', 'bb', 250),
|
||||
('II', 'aa', 652), ('BB', 'bb', 633), ('AA', 'aa', 239),
|
||||
('FF', 'aa', 670), ('BB', 'bb', 705), ('HH', 'bb', 963),
|
||||
('CC', 'bb', 346), ('II', 'bb', 671), ('BB', 'aa', 247),
|
||||
('AA', 'aa', 223), ('GG', 'aa', 480), ('HH', 'aa', 790),
|
||||
('FF', 'aa', 208), ('BB', 'bb', 711), ('EE', 'aa', 777),
|
||||
('DD', 'bb', 716), ('CC', 'aa', 759), ('CC', 'aa', 430),
|
||||
('CC', 'aa', 607), ('DD', 'bb', 794), ('GG', 'aa', 148),
|
||||
('GG', 'aa', 634), ('JJ', 'bb', 257), ('DD', 'bb', 959),
|
||||
('FF', 'bb', 726), ('BB', 'aa', 762), ('JJ', 'bb', 336),
|
||||
('GG', 'aa', 335), ('HH', 'bb', 330), ('GG', 'bb', 160),
|
||||
('JJ', 'bb', 839), ('FF', 'aa', 618), ('BB', 'aa', 393),
|
||||
('EE', 'bb', 629), ('FF', 'aa', 667), ('AA', 'bb', 870),
|
||||
('FF', 'bb', 102), ('JJ', 'aa', 113), ('DD', 'aa', 224),
|
||||
('AA', 'bb', 627), ('HH', 'bb', 730), ('II', 'bb', 443),
|
||||
('HH', 'bb', 133), ('EE', 'bb', 252), ('II', 'bb', 805),
|
||||
('BB', 'bb', 786), ('EE', 'bb', 768), ('HH', 'bb', 683),
|
||||
('DD', 'bb', 238), ('DD', 'aa', 256);
|
||||
}
|
||||
|
||||
foreach {tn frame} {
|
||||
1 { GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING }
|
||||
2 { GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW }
|
||||
3 { GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING }
|
||||
4 { GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING }
|
||||
5 { GROUPS BETWEEN 1 PRECEDING AND 2 PRECEDING }
|
||||
6 { GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING }
|
||||
7 { GROUPS BETWEEN 3 PRECEDING AND 1 PRECEDING }
|
||||
8 { GROUPS BETWEEN 3 PRECEDING AND 0 PRECEDING }
|
||||
9 { GROUPS BETWEEN 2 PRECEDING AND CURRENT ROW }
|
||||
10 { GROUPS BETWEEN 3 PRECEDING AND 0 FOLLOWING }
|
||||
11 { GROUPS BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING }
|
||||
12 { GROUPS BETWEEN CURRENT ROW AND 0 FOLLOWING }
|
||||
13 { GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING }
|
||||
14 { GROUPS BETWEEN CURRENT ROW AND 100 FOLLOWING }
|
||||
15 { GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
|
||||
16 { GROUPS BETWEEN 0 FOLLOWING AND 0 FOLLOWING }
|
||||
17 { GROUPS BETWEEN 1 FOLLOWING AND 0 FOLLOWING }
|
||||
18 { GROUPS BETWEEN 1 FOLLOWING AND 5 FOLLOWING }
|
||||
19 { GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING }
|
||||
|
||||
} {
|
||||
execsql_test 1.$tn.1 "
|
||||
SELECT a, b, sum(c) OVER (ORDER BY a $frame) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
execsql_test 1.$tn.2 "
|
||||
SELECT a, b, sum(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
execsql_test 1.$tn.3 "
|
||||
SELECT a, b, rank() OVER (ORDER BY a $frame) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
execsql_test 1.$tn.4 "
|
||||
SELECT a, b, max(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
execsql_test 1.$tn.5 "
|
||||
SELECT a, b, min(c) OVER (ORDER BY a,b $frame) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
|
||||
set f2 "$frame EXCLUDE CURRENT ROW"
|
||||
|
||||
execsql_test 1.$tn.6 "
|
||||
SELECT a, b, sum(c) OVER (ORDER BY a $f2) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
execsql_test 1.$tn.7 "
|
||||
SELECT a, b, sum(c) OVER (ORDER BY a,b $f2) FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
|
||||
execsql_test 1.$tn.8 "
|
||||
SELECT a, b,
|
||||
sum(c) OVER (ORDER BY a $f2),
|
||||
sum(c) OVER (ORDER BY a $frame),
|
||||
sum(c) OVER (ORDER BY a,b $f2),
|
||||
sum(c) OVER (ORDER BY a,b $frame)
|
||||
FROM t3 ORDER BY 1, 2, 3;
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
foreach {tn ex} {
|
||||
1 { EXCLUDE NO OTHERS }
|
||||
2 { EXCLUDE CURRENT ROW }
|
||||
3 { EXCLUDE GROUP }
|
||||
4 { EXCLUDE TIES }
|
||||
} {
|
||||
execsql_test 2.$tn.1 "
|
||||
SELECT row_number() OVER win
|
||||
FROM t3
|
||||
WINDOW win AS (
|
||||
ORDER BY c, b, a
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $ex
|
||||
)
|
||||
"
|
||||
|
||||
execsql_test 2.$tn.2 "
|
||||
SELECT nth_value(c, 14) OVER win
|
||||
FROM t3
|
||||
WINDOW win AS (
|
||||
ORDER BY c, b, a
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $ex
|
||||
)
|
||||
"
|
||||
|
||||
execsql_test 2.$tn.3 "
|
||||
SELECT min(c) OVER win, max(c) OVER win, sum(c) OVER win FROM t3
|
||||
WINDOW win AS (
|
||||
ORDER BY c, b, a
|
||||
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW $ex
|
||||
) ORDER BY a, b, c;
|
||||
"
|
||||
}
|
||||
|
||||
==========
|
||||
|
||||
execsql_test 3.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a REAL, b INTEGER);
|
||||
INSERT INTO t1 VALUES
|
||||
(5, 10), (10, 20), (13, 26), (13, 26),
|
||||
(15, 30), (20, 40), (22,80), (30, 90);
|
||||
}
|
||||
|
||||
foreach {tn frame} {
|
||||
1 { ORDER BY a RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING }
|
||||
2 { ORDER BY a RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING }
|
||||
3 { ORDER BY a RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING }
|
||||
4 { ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 5 FOLLOWING }
|
||||
5 { ORDER BY a DESC RANGE BETWEEN 10 PRECEDING AND 5 PRECEDING }
|
||||
6 { ORDER BY a DESC RANGE BETWEEN 2 FOLLOWING AND 3 FOLLOWING }
|
||||
|
||||
7 { ORDER BY a RANGE BETWEEN 5.1 PRECEDING AND 5.3 FOLLOWING }
|
||||
8 { ORDER BY a RANGE BETWEEN 10.2 PRECEDING AND 5.4 PRECEDING }
|
||||
9 { ORDER BY a RANGE BETWEEN 2.6 FOLLOWING AND 3.5 FOLLOWING }
|
||||
10 { ORDER BY a DESC RANGE BETWEEN 5.7 PRECEDING AND 5.8 FOLLOWING }
|
||||
11 { ORDER BY a DESC RANGE BETWEEN UNBOUNDED PRECEDING AND 5.9 PRECEDING }
|
||||
12 { ORDER BY a DESC RANGE BETWEEN 2.1 FOLLOWING AND UNBOUNDED FOLLOWING }
|
||||
13 { ORDER BY a RANGE 5.1 PRECEDING }
|
||||
} {
|
||||
execsql_test 3.$tn "
|
||||
SELECT CAST(a AS INTEGER), sum(b) OVER win FROM t1 WINDOW win AS ($frame)
|
||||
"
|
||||
}
|
||||
|
||||
==========
|
||||
|
||||
execsql_test 4.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER);
|
||||
INSERT INTO t1 VALUES
|
||||
(NULL, 1), (NULL, 2), (NULL, 3), (10, 4), (10, 5);
|
||||
}
|
||||
|
||||
execsql_test 4.1.1 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
|
||||
) FROM t1 ORDER BY 1;
|
||||
}
|
||||
execsql_test 4.1.2 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING
|
||||
) FROM t1 ORDER BY 1;
|
||||
}
|
||||
|
||||
execsql_test 4.2.1 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
|
||||
) FROM t1 ORDER BY 1 NULLS FIRST;
|
||||
}
|
||||
|
||||
execsql_test 4.2.2 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING
|
||||
) FROM t1 ORDER BY 1 NULLS FIRST;
|
||||
}
|
||||
|
||||
execsql_test 4.3.1 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING
|
||||
) FROM t1 ORDER BY 1 NULLS FIRST;
|
||||
}
|
||||
|
||||
execsql_test 4.4.1 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1 NULLS FIRST;
|
||||
}
|
||||
|
||||
execsql_test 4.4.2 {
|
||||
SELECT sum(b) OVER (
|
||||
ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1 NULLS FIRST;
|
||||
}
|
||||
|
||||
==========
|
||||
|
||||
execsql_test 5.0 {
|
||||
INSERT INTO t3 VALUES
|
||||
(NULL, 'bb', 355), (NULL, 'cc', 158), (NULL, 'aa', 399),
|
||||
('JJ', NULL, 839), ('FF', NULL, 618), ('BB', NULL, 393),
|
||||
(NULL, 'bb', 629), (NULL, NULL, 667), (NULL, NULL, 870);
|
||||
}
|
||||
|
||||
foreach {tn ex} {
|
||||
1 { EXCLUDE NO OTHERS }
|
||||
2 { EXCLUDE CURRENT ROW }
|
||||
3 { EXCLUDE GROUP }
|
||||
4 { EXCLUDE TIES }
|
||||
} {
|
||||
foreach {tn2 frame} {
|
||||
1 { RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
|
||||
2 { ORDER BY a NULLS FIRST
|
||||
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
|
||||
3 { PARTITION BY coalesce(a, '')
|
||||
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING }
|
||||
4 { ORDER BY a NULLS FIRST GROUPS 6 PRECEDING }
|
||||
5 { ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING }
|
||||
6 { ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING }
|
||||
7 { ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST
|
||||
ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING }
|
||||
} {
|
||||
execsql_test 5.$tn.$tn2.1 "
|
||||
SELECT max(c) OVER win,
|
||||
min(c) OVER win,
|
||||
count(a) OVER win
|
||||
FROM t3
|
||||
WINDOW win AS ( $frame $ex )
|
||||
ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
|
||||
"
|
||||
|
||||
execsql_test 5.$tn.$tn2.2 "
|
||||
SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win,
|
||||
rank() OVER win,
|
||||
dense_rank() OVER win
|
||||
FROM t3
|
||||
WINDOW win AS ( $frame $ex )
|
||||
ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
4851
test/window8.test
Normal file
4851
test/window8.test
Normal file
File diff suppressed because it is too large
Load Diff
52
test/windowerr.tcl
Normal file
52
test/windowerr.tcl
Normal file
@@ -0,0 +1,52 @@
|
||||
# 2018 May 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname $argv0] pg_common.tcl]
|
||||
|
||||
#=========================================================================
|
||||
|
||||
start_test windowerr "2019 March 01"
|
||||
ifcapable !windowfunc
|
||||
|
||||
execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4);
|
||||
INSERT INTO t1 VALUES(5, 5);
|
||||
}
|
||||
|
||||
foreach {tn frame} {
|
||||
1 "ORDER BY a ROWS BETWEEN -1 PRECEDING AND 1 FOLLOWING"
|
||||
2 "ORDER BY a ROWS BETWEEN 1 PRECEDING AND -1 FOLLOWING"
|
||||
|
||||
3 "ORDER BY a RANGE BETWEEN -1 PRECEDING AND 1 FOLLOWING"
|
||||
4 "ORDER BY a RANGE BETWEEN 1 PRECEDING AND -1 FOLLOWING"
|
||||
|
||||
5 "ORDER BY a GROUPS BETWEEN -1 PRECEDING AND 1 FOLLOWING"
|
||||
6 "ORDER BY a GROUPS BETWEEN 1 PRECEDING AND -1 FOLLOWING"
|
||||
|
||||
7 "ORDER BY a,b RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING"
|
||||
|
||||
8 "PARTITION BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING"
|
||||
} {
|
||||
errorsql_test 1.$tn "
|
||||
SELECT a, sum(b) OVER (
|
||||
$frame
|
||||
) FROM t1 ORDER BY 1
|
||||
"
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
89
test/windowerr.test
Normal file
89
test/windowerr.test
Normal file
@@ -0,0 +1,89 @@
|
||||
# 2019 March 01
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
####################################################
|
||||
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
|
||||
####################################################
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix windowerr
|
||||
|
||||
ifcapable !windowfunc { finish_test ; return }
|
||||
do_execsql_test 1.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4);
|
||||
INSERT INTO t1 VALUES(5, 5);
|
||||
} {}
|
||||
|
||||
# PG says ERROR: frame starting offset must not be negative
|
||||
do_test 1.1 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a ROWS BETWEEN -1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: frame ending offset must not be negative
|
||||
do_test 1.2 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a ROWS BETWEEN 1 PRECEDING AND -1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: invalid preceding or following size in window function
|
||||
do_test 1.3 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN -1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: invalid preceding or following size in window function
|
||||
do_test 1.4 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a RANGE BETWEEN 1 PRECEDING AND -1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: frame starting offset must not be negative
|
||||
do_test 1.5 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN -1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: frame ending offset must not be negative
|
||||
do_test 1.6 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a GROUPS BETWEEN 1 PRECEDING AND -1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
|
||||
do_test 1.7 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
ORDER BY a,b RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
# PG says ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
|
||||
do_test 1.8 { catch { execsql {
|
||||
SELECT a, sum(b) OVER (
|
||||
PARTITION BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||
) FROM t1 ORDER BY 1
|
||||
} } } 1
|
||||
|
||||
finish_test
|
@@ -28,7 +28,7 @@ do_execsql_test 1.0 {
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -start 1 -faults oom-* -prep {
|
||||
do_faultsim_test 1 -start 1 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
|
@@ -205,6 +205,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "ESCAPE", "TK_ESCAPE", ALWAYS },
|
||||
{ "EXCEPT", "TK_EXCEPT", COMPOUND },
|
||||
{ "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
|
||||
{ "EXCLUDE", "TK_EXCLUDE", WINDOWFUNC },
|
||||
{ "EXISTS", "TK_EXISTS", ALWAYS },
|
||||
{ "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
|
||||
{ "FAIL", "TK_FAIL", CONFLICT|TRIGGER },
|
||||
@@ -216,6 +217,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "FULL", "TK_JOIN_KW", ALWAYS },
|
||||
{ "GLOB", "TK_LIKE_KW", ALWAYS },
|
||||
{ "GROUP", "TK_GROUP", ALWAYS },
|
||||
{ "GROUPS", "TK_GROUPS", WINDOWFUNC },
|
||||
{ "HAVING", "TK_HAVING", ALWAYS },
|
||||
{ "IF", "TK_IF", ALWAYS },
|
||||
{ "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER },
|
||||
@@ -238,7 +240,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "LIMIT", "TK_LIMIT", ALWAYS },
|
||||
{ "MATCH", "TK_MATCH", ALWAYS },
|
||||
{ "NATURAL", "TK_JOIN_KW", ALWAYS },
|
||||
{ "NO", "TK_NO", FKEY },
|
||||
{ "NO", "TK_NO", FKEY|WINDOWFUNC },
|
||||
{ "NOT", "TK_NOT", ALWAYS },
|
||||
{ "NOTHING", "TK_NOTHING", UPSERT },
|
||||
{ "NOTNULL", "TK_NOTNULL", ALWAYS },
|
||||
@@ -248,6 +250,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "ON", "TK_ON", ALWAYS },
|
||||
{ "OR", "TK_OR", ALWAYS },
|
||||
{ "ORDER", "TK_ORDER", ALWAYS },
|
||||
{ "OTHERS", "TK_OTHERS", WINDOWFUNC },
|
||||
{ "OUTER", "TK_JOIN_KW", ALWAYS },
|
||||
{ "OVER", "TK_OVER", WINDOWFUNC },
|
||||
{ "PARTITION", "TK_PARTITION", WINDOWFUNC },
|
||||
@@ -277,6 +280,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "TEMP", "TK_TEMP", ALWAYS },
|
||||
{ "TEMPORARY", "TK_TEMP", ALWAYS },
|
||||
{ "THEN", "TK_THEN", ALWAYS },
|
||||
{ "TIES", "TK_TIES", WINDOWFUNC },
|
||||
{ "TO", "TK_TO", ALWAYS },
|
||||
{ "TRANSACTION", "TK_TRANSACTION", ALWAYS },
|
||||
{ "TRIGGER", "TK_TRIGGER", TRIGGER },
|
||||
|
Reference in New Issue
Block a user