1
0
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:
dan
2019-03-26 13:08:34 +00:00
24 changed files with 40229 additions and 2384 deletions

View File

@@ -1,5 +1,5 @@
C Fix\san\sobsolete\scomment\sin\sthe\sCLI.\s\sNo\scode\schanges. 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-25T22:05:22.540 D 2019-03-26T13:08:34.839
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -457,7 +457,7 @@ F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 6bea02598917ad9549d2d0c78bf8cc288eeb7a0b0f4298cbe1713db01340f9be F src/btree.c a644e8f3b71205e1e360ed5a28d8fc8feaa5c63fee3a49a36711ff83f4bdf6d2
F src/btree.h 63b94fb38ce571c15eb6a3661815561b501d23d5948b2d1e951fbd7a2d04e8d3 F src/btree.h 63b94fb38ce571c15eb6a3661815561b501d23d5948b2d1e951fbd7a2d04e8d3
F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
F src/build.c 7c8851893fb616115d7f6ae1e07df5076c6d4a8f592cd2affa04f3112176c38c F src/build.c 7c8851893fb616115d7f6ae1e07df5076c6d4a8f592cd2affa04f3112176c38c
@@ -505,7 +505,7 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
F src/parse.y 741a270b7f2f85bc5d026d06fb5a9ccba5335304ff2831e1cb44b36cd0da6006 F src/parse.y a020386af1739371b2eafba077497aacf2a840d1a178508dc6f8c19448e42054
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
@@ -514,14 +514,14 @@ F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3 F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3
F src/printf.c 93a3d539019264683a444bc043c875e9a6cca43fe935ae7bf6cfff0af3bba118 F src/printf.c 93a3d539019264683a444bc043c875e9a6cca43fe935ae7bf6cfff0af3bba118
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 09419ad5c432190b69be7c0c326e03abb548a97c2c50675b81b459e1b382d1d2 F src/resolve.c f20cb5b953bd927e8c6b6e01662cce066a632b5d3a21d2938b93de0825aef5d5
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49 F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49
F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810 F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810
F src/sqlite.h.in 633ca2147938402fe43118db929a7949dde3e2a08c138e40bbdec12a0e696129 F src/sqlite.h.in 633ca2147938402fe43118db929a7949dde3e2a08c138e40bbdec12a0e696129
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
F src/sqliteInt.h f253c4ec15e577a293a462e5049f8ea1d0c7a31819b3a88acdd24698df8f4d0b F src/sqliteInt.h 19641f2402ef4e45fd2e222f5a45bb24e3f89a519059d35ce2819f46ce5e1a1e
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -587,7 +587,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432 F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432
F src/vacuum.c 532553ee1d47f69c1198858107b1f3af3d16af25f2ab4ce3b1263d9e333f26e2 F src/vacuum.c 532553ee1d47f69c1198858107b1f3af3d16af25f2ab4ce3b1263d9e333f26e2
F src/vdbe.c f1e7b5320df80ff58c67176e35cb48062cbda2a9c9811f11db5faa48071d3fe4 F src/vdbe.c 8f824b423460fbbd6a140f557b9d3cb26fa55404d03aee43584d11c7d1011b02
F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237 F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f
F src/vdbeapi.c 7a052df80d7e2e55382076174633e888f21fe200feb5d49b1b441b4c38ab851a F src/vdbeapi.c 7a052df80d7e2e55382076174633e888f21fe200feb5d49b1b441b4c38ab851a
@@ -605,7 +605,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88 F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
F src/wherecode.c 6fa4056c5ce019e4a8af33795906340176813cb3c1236f4b7b08df76a1b6287b F src/wherecode.c 6fa4056c5ce019e4a8af33795906340176813cb3c1236f4b7b08df76a1b6287b
F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c
F src/window.c df2456386e0b1553a8d1fcf3a0ddc4c058fe2c650ea8c74b6bf8862082ddafc9 F src/window.c 9849eee7e9e3e596f26cd84295d68ff501ccbc37287840fa07bc1717d6d09819
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1197,8 +1197,8 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 52d2c37fe8cc07ec7362024c214b04bb69432995b3a984a3fbabc60fa6ada3ee F test/permutations.test b8f0da2f53ef1bd7ff149a140ee625aa7276c94ae15eb9acc2d8ed4af8f22b13
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 F test/pg_common.tcl 4740dc35190d6acdab14c097783331361301ab504a94d948f6afbb56ce0a51e8
F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867 F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
@@ -1677,16 +1677,22 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 53db04133c48065c7554cb7195b0d23b879feb2dc9dacf0945a259c423687133 F test/window1.test 7484bf9a2ef2d845a50c9aff866efb8cd9d244b5916a9e97fb384e05f33d242b
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98 F test/window3.test e9959a993c8a71e96433be8daaa1827d78b8921e4f12debd7bdbeb3c856ef3cb
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb F test/window4.tcl 5fbaab489677914ee5686b2008426e336daf88a2f58be7df92757f780a5ebf91
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62 F test/window4.test bf8f86586ce101bf98e2306e597fa24aadc96c58d70ba4d11f956cf8ca4e0be3
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3 F test/window6.test 604890f2b0f976339e6a1774cd90d48840e57a54b4f21a8b4b3047aa2c9787d1
F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b 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/with1.test a07b5aad7f77acdf13e52e8814ea94606fcc72e9ea4c99baf293e9d7c63940be
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 8d26920c88283e0a473ceebd3451554922108ce7b2a6a1157c47eb0a7011212c F test/with3.test 8d26920c88283e0a473ceebd3451554922108ce7b2a6a1157c47eb0a7011212c
@@ -1735,7 +1741,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3 F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c 1f7f2ac1d9f262c08b67faaca47e6a68262ff39113fa4b27d1db2843b4c33e73 F tool/mkkeywordhash.c 127d0b86eea32a461b79b6c6b11fa5fd223787b681156d682bf1824bb20e2494
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
@@ -1807,7 +1813,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e775ef002dd33e6bcbeec8d4b6ad7f59749e35548c7a59c9fa3bcfdc5cc50730 P fade103cbac1b067f9544935b767f36dc266aceb3269cc84a3ae3b04ad9a4823 9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
R 3d12cfa0cda4f35a3d1533c43ce31db3 R bdc22793cb51647fca24f70e83877204
U drh T +closed 9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
Z b5e63031019719c1b59c8c1822668f3c U dan
Z 8d3e4b02d8e1dd0a57c5b612deb65ffe

View File

@@ -1 +1 @@
fade103cbac1b067f9544935b767f36dc266aceb3269cc84a3ae3b04ad9a4823 c6da39115d3e2b0fd3a03c4bcae8ee8b05a6bbd6b11f8c54712fbff6387f610d

View File

@@ -8834,9 +8834,12 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag ); assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( pCur->ix<pCur->pPage->nCell );
assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); 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; iCellDepth = pCur->iPage;
iCellIdx = pCur->ix; iCellIdx = pCur->ix;

View File

@@ -218,6 +218,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
%endif SQLITE_OMIT_COMPOUND_SELECT %endif SQLITE_OMIT_COMPOUND_SELECT
%ifndef SQLITE_OMIT_WINDOWFUNC %ifndef SQLITE_OMIT_WINDOWFUNC
CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC %endif SQLITE_OMIT_WINDOWFUNC
REINDEX RENAME CTIME_KW IF 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(Z). { A = Z; }
windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). { windowdefn_list(A) ::= windowdefn_list(Y) COMMA windowdefn(Z). {
assert( Z!=0 ); assert( Z!=0 );
sqlite3WindowChain(pParse, Z, Y);
Z->pNextWin = Y; Z->pNextWin = Y;
A = Z; A = Z;
} }
%type windowdefn {Window*} %type windowdefn {Window*}
%destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);} %destructor windowdefn {sqlite3WindowDelete(pParse->db, $$);}
windowdefn(A) ::= nm(X) AS window(Y). { windowdefn(A) ::= nm(X) AS LP window(Y) RP. {
if( ALWAYS(Y) ){ if( ALWAYS(Y) ){
Y->zName = sqlite3DbStrNDup(pParse->db, X.z, X.n); 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} %type frame_bound_e {struct FrameBound}
%destructor frame_bound_e {sqlite3ExprDelete(pParse->db, $$.pExpr);} %destructor frame_bound_e {sqlite3ExprDelete(pParse->db, $$.pExpr);}
window(A) ::= LP part_opt(X) orderby_opt(Y) frame_opt(Z) RP. { 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; A = Z;
if( ALWAYS(A) ){
A->pPartition = X;
A->pOrderBy = Y;
} }
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) ::= . { 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). { 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); 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). { 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); 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) ::= RANGE. { A = TK_RANGE; }
range_or_rows(A) ::= ROWS. { A = TK_ROWS; } 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; } 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) ::= CURRENT ROW. { A.eType = TK_CURRENT ; A.pExpr = 0; }
frame_bound(A) ::= expr(X) FOLLOWING. { A.eType = TK_FOLLOWING; A.pExpr = X; } 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*} %type window_clause {Window*}
%destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);} %destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);}
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; } window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
%type over_clause {Window*} %type over_clause {Window*}
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);} %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; A = Z;
assert( A!=0 ); assert( A!=0 );
A->pFilter = W; A->pFilter = W;

View File

@@ -1424,7 +1424,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/ */
for(i=0; i<p->pSrc->nSrc; i++){ for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[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 */ NameContext *pNC; /* Used to iterate name contexts */
int nRef = 0; /* Refcount for pOuterNC and outer contexts */ int nRef = 0; /* Refcount for pOuterNC and outer contexts */
const char *zSavedContext = pParse->zAuthContext; const char *zSavedContext = pParse->zAuthContext;

View File

@@ -1691,7 +1691,6 @@ struct FuncDestructor {
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() 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 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 */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
/* /*
@@ -3555,11 +3554,14 @@ struct TreeView {
*/ */
struct Window { struct Window {
char *zName; /* Name of window (may be NULL) */ 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 *pPartition; /* PARTITION BY clause */
ExprList *pOrderBy; /* ORDER BY clause */ ExprList *pOrderBy; /* ORDER BY clause */
u8 eType; /* TK_RANGE or TK_ROWS */ u8 eType; /* TK_RANGE or TK_ROWS */
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
u8 eEnd; /* 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 *pStart; /* Expression for "<expr> PRECEDING" */
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
Window *pNextWin; /* Next window function belonging to this SELECT */ Window *pNextWin; /* Next window function belonging to this SELECT */
@@ -3570,17 +3572,19 @@ struct Window {
int regResult; int regResult;
int csrApp; /* Function cursor (used by min/max) */ int csrApp; /* Function cursor (used by min/max) */
int regApp; /* Function register (also used by min/max) */ int regApp; /* Function register (also used by min/max) */
int regPart; /* First in a set of registers holding PARTITION BY int regPart; /* Array of registers for PARTITION BY values */
** and ORDER BY values for the window */
Expr *pOwner; /* Expression object this window is attached to */ Expr *pOwner; /* Expression object this window is attached to */
int nBufferCol; /* Number of columns in buffer table */ int nBufferCol; /* Number of columns in buffer table */
int iArgCol; /* Offset of first argument for this function */ int iArgCol; /* Offset of first argument for this function */
int regOne; /* Register containing constant value 1 */
int regStartRowid;
int regEndRowid;
}; };
#ifndef SQLITE_OMIT_WINDOWFUNC #ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3WindowDelete(sqlite3*, Window*); void sqlite3WindowDelete(sqlite3*, Window*);
void sqlite3WindowListDelete(sqlite3 *db, Window *p); 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*); void sqlite3WindowAttach(Parse*, Expr*, Window*);
int sqlite3WindowCompare(Parse*, Window*, Window*); int sqlite3WindowCompare(Parse*, Window*, Window*);
void sqlite3WindowCodeInit(Parse*, Window*); void sqlite3WindowCodeInit(Parse*, Window*);
@@ -3591,6 +3595,8 @@ void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
Window *sqlite3WindowListDup(sqlite3 *db, Window *p); Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
void sqlite3WindowFunctions(void); void sqlite3WindowFunctions(void);
void sqlite3WindowChain(Parse*, Window*, Window*);
Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
#else #else
# define sqlite3WindowDelete(a,b) # define sqlite3WindowDelete(a,b)
# define sqlite3WindowFunctions() # define sqlite3WindowFunctions()

View File

@@ -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 ** OP_Eq or OP_Ne) then take the jump or not depending on whether
** or not both operands are null. ** or not both operands are null.
*/ */
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 ); assert( (flags1 & MEM_Cleared)==0 );
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB ); assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 ); 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 */ res = 0; /* Operands are equal */
}else{ }else{
res = 1; /* Operands are not equal */ res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
} }
}else{ }else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL, /* SQLITE_NULLEQ is clear and at least one operand is NULL,
@@ -3606,6 +3605,7 @@ case OP_OpenDup: {
pCx->pKeyInfo = pOrig->pKeyInfo; pCx->pKeyInfo = pOrig->pKeyInfo;
pCx->isTable = pOrig->isTable; pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot; pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR, rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor); pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor /* 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 ); assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
#ifndef SQLITE_OMIT_WINDOWFUNC #ifndef SQLITE_OMIT_WINDOWFUNC
if( pOp->p3 ){ if( pOp->p3 ){
memAboutToChange(p, &aMem[pOp->p3]);
rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc);
pMem = &aMem[pOp->p3]; pMem = &aMem[pOp->p3];
}else }else

File diff suppressed because it is too large Load Diff

View File

@@ -1032,13 +1032,15 @@ test_suite "rbu" -description {
test_suite "no_optimization" -description { test_suite "no_optimization" -description {
Run test scripts with optimizations disabled using the Run test scripts with optimizations disabled using the
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface. sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface.
} -files { } -files [
where.test where2.test where3.test where4.test where5.test test_set \
where6.test where7.test where8.test where9.test [glob -nocomplain $::testdir/window*.test] \
whereA.test whereB.test wherelimit.test where.test where2.test where3.test where4.test where5.test \
select1.test select2.test select3.test select4.test select5.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 select7.test select8.test selectA.test selectC.test
} -dbconfig { ] -dbconfig {
optimization_control $::dbhandle all 0 optimization_control $::dbhandle all 0
} }

View File

@@ -40,17 +40,26 @@ proc execsql {sql} {
#puts $lSql #puts $lSql
set ret "" set ret ""
set nChar 0
foreach stmt $lSql { foreach stmt $lSql {
set res [pg_exec $::db $stmt] set res [pg_exec $::db $stmt]
set err [pg_result $res -error] set err [pg_result $res -error]
if {$err!=""} { error $err } if {$err!=""} { error $err }
for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} { for {set i 0} {$i < [pg_result $res -numTuples]} {incr i} {
if {$i==0} { set t [pg_result $res -getTuple $i]
set ret [pg_result $res -getTuple 0] set nNew [string length $t]
if {$nChar>0 && ($nChar+$nNew+3)>75} {
append ret "\n "
set nChar 0
} else { } 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 pg_result $res -clear
} }
@@ -61,12 +70,28 @@ proc execsql {sql} {
proc execsql_test {tn sql} { proc execsql_test {tn sql} {
set res [execsql $sql] set res [execsql $sql]
set sql [string map {string_agg group_concat} $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 "do_execsql_test $tn {"
puts $::fd " [string trim $sql]" puts $::fd " [string trim $sql]"
puts $::fd "} {$res}" puts $::fd "} {$res}"
puts $::fd "" 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 # Same as [execsql_test], except coerce all results to floating point values
# with two decimal points. # with two decimal points.
# #
@@ -88,10 +113,12 @@ do_test $tn {
lappend myres [format $F [set r]] lappend myres [format $F [set r]]
} }
set res2 {$res2} set res2 {$res2}
set i 0
foreach r [set myres] r2 [set res2] { foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-$T) || [set r]>([set r2]+$T)} { 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]" error "list element [set i] does not match: got=[set r] expected=[set r2]"
} }
incr i
} }
set {} {} set {} {}
} {} } {}

View File

@@ -720,10 +720,299 @@ do_execsql_test 17.3 {
ORDER BY 10+sum(a) OVER (ORDER BY a) DESC; ORDER BY 10+sum(a) OVER (ORDER BY a) DESC;
} {16 13 11} } {16 13 11}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test error cases from chaining window definitions.
# #
reset_db reset_db
do_execsql_test 18.0 { 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 t1 ( t1_id INTEGER PRIMARY KEY );
CREATE TABLE t2 ( t2_id INTEGER PRIMARY KEY ); CREATE TABLE t2 ( t2_id INTEGER PRIMARY KEY );
CREATE TABLE t3 ( t3_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); INSERT INTO t3 VALUES(10), (11), (12);
} }
do_execsql_test 18.1 { do_execsql_test 25.1 {
SELECT t1.* FROM t1, t2 WHERE SELECT t1.* FROM t1, t2 WHERE
t1_id=t2_id AND t1_id IN ( t1_id=t2_id AND t1_id IN (
SELECT t1_id + row_number() OVER ( ORDER BY t1_id ) FROM t3 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 SELECT t1.* FROM t1, t2 WHERE
t1_id=t2_id AND t1_id IN ( t1_id=t2_id AND t1_id IN (
SELECT row_number() OVER ( ORDER BY t1_id ) FROM t3 SELECT row_number() OVER ( ORDER BY t1_id ) FROM t3
) )
} {3} } {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 finish_test

View File

@@ -21,7 +21,6 @@ execsql_test 1.0 {
DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t2;
CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER); CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);
INSERT INTO t2(a, b) VALUES 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), (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), (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), (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" 15 "ROWS BETWEEN 4 PRECEDING AND UNBOUNDED FOLLOWING"
16 "ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" 16 "ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING"
17 "ROWS BETWEEN 4 FOLLOWING 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.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" 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 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 " execsql_test 1.$tn.15.1 "
SELECT count(*) OVER win, string_agg(CAST(b AS TEXT), '.') SELECT count(*) OVER win, string_agg(CAST(b AS TEXT), '.')
FILTER (WHERE a%2=0) OVER win FROM t2 FILTER (WHERE a%2=0) OVER win FROM t2

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
# 2018 May 19 ## 2018 May 19
# #
# The author disclaims copyright to this source code. In place of # The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing: # a legal notice, here is a blessing:

View File

@@ -150,7 +150,8 @@ do_execsql_test 2.4.1 {
SELECT group_concat(b, '.') OVER ( SELECT group_concat(b, '.') OVER (
ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) FROM t4 ) 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 { do_execsql_test 3.0 {
DROP TABLE IF EXISTS t5; DROP TABLE IF EXISTS t5;
@@ -1224,10 +1225,12 @@ do_test 9.3 {
lappend myres [format %.4f [set r]] 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 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] { foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { 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]" error "list element [set i] does not match: got=[set r] expected=[set r2]"
} }
incr i
} }
set {} {} set {} {}
} {} } {}
@@ -1247,10 +1250,12 @@ do_test 9.6 {
lappend myres [format %.4f [set r]] lappend myres [format %.4f [set r]]
} }
set res2 {0.0000 0.0000 0.0000} set res2 {0.0000 0.0000 0.0000}
set i 0
foreach r [set myres] r2 [set res2] { foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { 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]" error "list element [set i] does not match: got=[set r] expected=[set r2]"
} }
incr i
} }
set {} {} set {} {}
} {} } {}
@@ -1262,10 +1267,12 @@ do_test 9.7 {
lappend myres [format %.4f [set r]] lappend myres [format %.4f [set r]]
} }
set res2 {1.0000 1.0000 1.0000} set res2 {1.0000 1.0000 1.0000}
set i 0
foreach r [set myres] r2 [set res2] { foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} { 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]" error "list element [set i] does not match: got=[set r] expected=[set r2]"
} }
incr i
} }
set {} {} set {} {}
} {} } {}

View File

@@ -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 1 1 2 1,2 3 1,2,3 4 2,3,4 5 3,4,5
} }
do_catchsql_test 9.1 { #do_catchsql_test 9.1 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5) # 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) # SELECT x, group_concat(x) OVER (ORDER BY x RANGE 2 PRECEDING)
FROM c; # FROM c;
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}} #} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
#
do_catchsql_test 9.2 { #do_catchsql_test 9.2 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5) # 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) # SELECT x, group_concat(x) OVER (ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND 2 FOLLOWING)
FROM c; # FROM c;
} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}} #} {1 {RANGE must use only UNBOUNDED or CURRENT ROW}}
do_catchsql_test 9.3 { do_catchsql_test 9.3 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5) 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 ( SELECT count() OVER (
ORDER BY x ROWS $frame ORDER BY x ROWS $frame
) FROM c; ) FROM c;
" {1 {unsupported frame delimiter for ROWS}} " {1 {unsupported frame specification}}
} }
do_catchsql_test 9.8.1 { do_catchsql_test 9.8.1 {

91
test/window7.tcl Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

52
test/windowerr.tcl Normal file
View 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
View 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

View File

@@ -28,7 +28,7 @@ do_execsql_test 1.0 {
} }
faultsim_save_and_close 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 faultsim_restore_and_reopen
} -body { } -body {
execsql { execsql {

View File

@@ -205,6 +205,7 @@ static Keyword aKeywordTable[] = {
{ "ESCAPE", "TK_ESCAPE", ALWAYS }, { "ESCAPE", "TK_ESCAPE", ALWAYS },
{ "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXCEPT", "TK_EXCEPT", COMPOUND },
{ "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS }, { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
{ "EXCLUDE", "TK_EXCLUDE", WINDOWFUNC },
{ "EXISTS", "TK_EXISTS", ALWAYS }, { "EXISTS", "TK_EXISTS", ALWAYS },
{ "EXPLAIN", "TK_EXPLAIN", EXPLAIN }, { "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
{ "FAIL", "TK_FAIL", CONFLICT|TRIGGER }, { "FAIL", "TK_FAIL", CONFLICT|TRIGGER },
@@ -216,6 +217,7 @@ static Keyword aKeywordTable[] = {
{ "FULL", "TK_JOIN_KW", ALWAYS }, { "FULL", "TK_JOIN_KW", ALWAYS },
{ "GLOB", "TK_LIKE_KW", ALWAYS }, { "GLOB", "TK_LIKE_KW", ALWAYS },
{ "GROUP", "TK_GROUP", ALWAYS }, { "GROUP", "TK_GROUP", ALWAYS },
{ "GROUPS", "TK_GROUPS", WINDOWFUNC },
{ "HAVING", "TK_HAVING", ALWAYS }, { "HAVING", "TK_HAVING", ALWAYS },
{ "IF", "TK_IF", ALWAYS }, { "IF", "TK_IF", ALWAYS },
{ "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER }, { "IGNORE", "TK_IGNORE", CONFLICT|TRIGGER },
@@ -238,7 +240,7 @@ static Keyword aKeywordTable[] = {
{ "LIMIT", "TK_LIMIT", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS },
{ "MATCH", "TK_MATCH", ALWAYS }, { "MATCH", "TK_MATCH", ALWAYS },
{ "NATURAL", "TK_JOIN_KW", ALWAYS }, { "NATURAL", "TK_JOIN_KW", ALWAYS },
{ "NO", "TK_NO", FKEY }, { "NO", "TK_NO", FKEY|WINDOWFUNC },
{ "NOT", "TK_NOT", ALWAYS }, { "NOT", "TK_NOT", ALWAYS },
{ "NOTHING", "TK_NOTHING", UPSERT }, { "NOTHING", "TK_NOTHING", UPSERT },
{ "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NOTNULL", "TK_NOTNULL", ALWAYS },
@@ -248,6 +250,7 @@ static Keyword aKeywordTable[] = {
{ "ON", "TK_ON", ALWAYS }, { "ON", "TK_ON", ALWAYS },
{ "OR", "TK_OR", ALWAYS }, { "OR", "TK_OR", ALWAYS },
{ "ORDER", "TK_ORDER", ALWAYS }, { "ORDER", "TK_ORDER", ALWAYS },
{ "OTHERS", "TK_OTHERS", WINDOWFUNC },
{ "OUTER", "TK_JOIN_KW", ALWAYS }, { "OUTER", "TK_JOIN_KW", ALWAYS },
{ "OVER", "TK_OVER", WINDOWFUNC }, { "OVER", "TK_OVER", WINDOWFUNC },
{ "PARTITION", "TK_PARTITION", WINDOWFUNC }, { "PARTITION", "TK_PARTITION", WINDOWFUNC },
@@ -277,6 +280,7 @@ static Keyword aKeywordTable[] = {
{ "TEMP", "TK_TEMP", ALWAYS }, { "TEMP", "TK_TEMP", ALWAYS },
{ "TEMPORARY", "TK_TEMP", ALWAYS }, { "TEMPORARY", "TK_TEMP", ALWAYS },
{ "THEN", "TK_THEN", ALWAYS }, { "THEN", "TK_THEN", ALWAYS },
{ "TIES", "TK_TIES", WINDOWFUNC },
{ "TO", "TK_TO", ALWAYS }, { "TO", "TK_TO", ALWAYS },
{ "TRANSACTION", "TK_TRANSACTION", ALWAYS }, { "TRANSACTION", "TK_TRANSACTION", ALWAYS },
{ "TRIGGER", "TK_TRIGGER", TRIGGER }, { "TRIGGER", "TK_TRIGGER", TRIGGER },