blob: ee705deb0ca27bea78ded2d10f4dafde34fcfcec [file] [log] [blame]
dan86fb6e12018-05-16 20:58:07 +00001# 2018 May 8
2#
3# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
5#
6# May you do good and not evil.
7# May you find forgiveness for yourself and forgive others.
8# May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.
12#
13
14set testdir [file dirname $argv0]
15source $testdir/tester.tcl
16set testprefix window1
17
dan67a9b8e2018-06-22 20:51:35 +000018ifcapable !windowfunc {
19 finish_test
20 return
21}
dan86fb6e12018-05-16 20:58:07 +000022
23do_execsql_test 1.0 {
24 CREATE TABLE t1(a, b, c, d);
25 INSERT INTO t1 VALUES(1, 2, 3, 4);
26 INSERT INTO t1 VALUES(5, 6, 7, 8);
27 INSERT INTO t1 VALUES(9, 10, 11, 12);
28}
29
30do_execsql_test 1.1 {
31 SELECT sum(b) OVER () FROM t1
32} {18 18 18}
33
34do_execsql_test 1.2 {
35 SELECT a, sum(b) OVER () FROM t1
36} {1 18 5 18 9 18}
37
38do_execsql_test 1.3 {
39 SELECT a, 4 + sum(b) OVER () FROM t1
40} {1 22 5 22 9 22}
41
42do_execsql_test 1.4 {
43 SELECT a + 4 + sum(b) OVER () FROM t1
44} {23 27 31}
45
46do_execsql_test 1.5 {
47 SELECT a, sum(b) OVER (PARTITION BY c) FROM t1
48} {1 2 5 6 9 10}
49
50foreach {tn sql} {
51 1 "SELECT sum(b) OVER () FROM t1"
52 2 "SELECT sum(b) OVER (PARTITION BY c) FROM t1"
53 3 "SELECT sum(b) OVER (ORDER BY c) FROM t1"
54 4 "SELECT sum(b) OVER (PARTITION BY d ORDER BY c) FROM t1"
55 5 "SELECT sum(b) FILTER (WHERE a>0) OVER (PARTITION BY d ORDER BY c) FROM t1"
56 6 "SELECT sum(b) OVER (ORDER BY c RANGE UNBOUNDED PRECEDING) FROM t1"
57 7 "SELECT sum(b) OVER (ORDER BY c ROWS 45 PRECEDING) FROM t1"
58 8 "SELECT sum(b) OVER (ORDER BY c RANGE CURRENT ROW) FROM t1"
59 9 "SELECT sum(b) OVER (ORDER BY c RANGE BETWEEN UNBOUNDED PRECEDING
60 AND CURRENT ROW) FROM t1"
61 10 "SELECT sum(b) OVER (ORDER BY c ROWS BETWEEN UNBOUNDED PRECEDING
62 AND UNBOUNDED FOLLOWING) FROM t1"
63} {
64 do_test 2.$tn { lindex [catchsql $sql] 0 } 0
65}
66
67foreach {tn sql} {
68 1 "SELECT * FROM t1 WHERE sum(b) OVER ()"
69 2 "SELECT * FROM t1 GROUP BY sum(b) OVER ()"
70 3 "SELECT * FROM t1 GROUP BY a HAVING sum(b) OVER ()"
71} {
72 do_catchsql_test 3.$tn $sql {1 {misuse of window function sum()}}
73}
74
75do_execsql_test 4.0 {
76 CREATE TABLE t2(a, b, c);
77 INSERT INTO t2 VALUES(0, 0, 0);
78 INSERT INTO t2 VALUES(1, 1, 1);
79 INSERT INTO t2 VALUES(2, 0, 2);
80 INSERT INTO t2 VALUES(3, 1, 0);
81 INSERT INTO t2 VALUES(4, 0, 1);
82 INSERT INTO t2 VALUES(5, 1, 2);
83 INSERT INTO t2 VALUES(6, 0, 0);
84}
85
86do_execsql_test 4.1 {
87 SELECT a, sum(a) OVER (PARTITION BY b) FROM t2;
88} {
89 0 12 2 12 4 12 6 12 1 9 3 9 5 9
90}
91
92do_execsql_test 4.2 {
93 SELECT a, sum(a) OVER (PARTITION BY b) FROM t2 ORDER BY a;
94} {
95 0 12 1 9 2 12 3 9 4 12 5 9 6 12
96}
97
98do_execsql_test 4.3 {
99 SELECT a, sum(a) OVER () FROM t2 ORDER BY a;
100} {
101 0 21 1 21 2 21 3 21 4 21 5 21 6 21
102}
103
104do_execsql_test 4.4 {
105 SELECT a, sum(a) OVER (ORDER BY a) FROM t2;
106} {
107 0 0 1 1 2 3 3 6 4 10 5 15 6 21
108}
109
110do_execsql_test 4.5 {
111 SELECT a, sum(a) OVER (PARTITION BY b ORDER BY a) FROM t2 ORDER BY a
112} {
113 0 0 1 1 2 2 3 4 4 6 5 9 6 12
114}
115
dan2e362f92018-05-17 14:26:27 +0000116do_execsql_test 4.6 {
117 SELECT a, sum(a) OVER (PARTITION BY c ORDER BY a) FROM t2 ORDER BY a
118} {
119 0 0 1 1 2 2 3 3 4 5 5 7 6 9
120}
121
122do_execsql_test 4.7 {
123 SELECT a, sum(a) OVER (PARTITION BY b ORDER BY a DESC) FROM t2 ORDER BY a
124} {
125 0 12 1 9 2 12 3 8 4 10 5 5 6 6
126}
127
128do_execsql_test 4.8 {
129 SELECT a,
130 sum(a) OVER (PARTITION BY b ORDER BY a DESC),
131 sum(a) OVER (PARTITION BY c ORDER BY a)
132 FROM t2 ORDER BY a
133} {
134 0 12 0
135 1 9 1
136 2 12 2
137 3 8 3
138 4 10 5
139 5 5 7
140 6 6 9
141}
142
dane2f781b2018-05-17 19:24:08 +0000143do_execsql_test 4.9 {
144 SELECT a,
145 sum(a) OVER (ORDER BY a),
146 avg(a) OVER (ORDER BY a)
147 FROM t2 ORDER BY a
148} {
149 0 0 0.0
150 1 1 0.5
151 2 3 1.0
152 3 6 1.5
153 4 10 2.0
154 5 15 2.5
155 6 21 3.0
156}
157
danb6e9f7a2018-05-19 14:15:29 +0000158do_execsql_test 4.10.1 {
dane2f781b2018-05-17 19:24:08 +0000159 SELECT a,
160 count() OVER (ORDER BY a DESC),
161 group_concat(a, '.') OVER (ORDER BY a DESC)
162 FROM t2 ORDER BY a DESC
163} {
164 6 1 6
165 5 2 6.5
166 4 3 6.5.4
167 3 4 6.5.4.3
168 2 5 6.5.4.3.2
169 1 6 6.5.4.3.2.1
170 0 7 6.5.4.3.2.1.0
171}
172
danb6e9f7a2018-05-19 14:15:29 +0000173do_execsql_test 4.10.2 {
174 SELECT a,
175 count(*) OVER (ORDER BY a DESC),
176 group_concat(a, '.') OVER (ORDER BY a DESC)
177 FROM t2 ORDER BY a DESC
178} {
179 6 1 6
180 5 2 6.5
181 4 3 6.5.4
182 3 4 6.5.4.3
183 2 5 6.5.4.3.2
184 1 6 6.5.4.3.2.1
185 0 7 6.5.4.3.2.1.0
186}
187
dan6bc5c9e2018-06-04 18:55:11 +0000188do_catchsql_test 5.1 {
189 SELECT ntile(0) OVER (ORDER BY a) FROM t2;
190} {1 {argument of ntile must be a positive integer}}
191do_catchsql_test 5.2 {
192 SELECT ntile(-1) OVER (ORDER BY a) FROM t2;
193} {1 {argument of ntile must be a positive integer}}
194do_catchsql_test 5.3 {
195 SELECT ntile('zbc') OVER (ORDER BY a) FROM t2;
196} {1 {argument of ntile must be a positive integer}}
197do_execsql_test 5.4 {
198 CREATE TABLE t4(a, b);
199 SELECT ntile(1) OVER (ORDER BY a) FROM t4;
200} {}
201
dandacf1de2018-06-08 16:11:55 +0000202#-------------------------------------------------------------------------
203reset_db
204do_execsql_test 6.1 {
205 CREATE TABLE t1(x);
206 INSERT INTO t1 VALUES(7), (6), (5), (4), (3), (2), (1);
207
208 CREATE TABLE t2(x);
209 INSERT INTO t2 VALUES('b'), ('a');
210
211 SELECT x, count(*) OVER (ORDER BY x) FROM t1;
212} {1 1 2 2 3 3 4 4 5 5 6 6 7 7}
213
214do_execsql_test 6.2 {
215 SELECT * FROM t2, (SELECT x, count(*) OVER (ORDER BY x) FROM t1);
216} {
217 b 1 1 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 b 7 7
218 a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7
219}
220
dan26522d12018-06-11 18:16:51 +0000221do_catchsql_test 6.3 {
dan8b985602018-06-09 17:43:45 +0000222 SELECT x, lag(x) FILTER (WHERE (x%2)=0) OVER w FROM t1
223 WINDOW w AS (ORDER BY x)
224} {1 {FILTER clause may only be used with aggregate window functions}}
dan26522d12018-06-11 18:16:51 +0000225
226#-------------------------------------------------------------------------
227# Attempt to use a window function as an aggregate. And other errors.
228#
229reset_db
230do_execsql_test 7.0 {
231 CREATE TABLE t1(x, y);
232 INSERT INTO t1 VALUES(1, 2);
233 INSERT INTO t1 VALUES(3, 4);
234 INSERT INTO t1 VALUES(5, 6);
235 INSERT INTO t1 VALUES(7, 8);
236 INSERT INTO t1 VALUES(9, 10);
237}
238
239do_catchsql_test 7.1.1 {
240 SELECT nth_value(x, 1) FROM t1;
241} {1 {misuse of window function nth_value()}}
242do_catchsql_test 7.1.2 {
243 SELECT * FROM t1 WHERE nth_value(x, 1) OVER (ORDER BY y);
244} {1 {misuse of window function nth_value()}}
245do_catchsql_test 7.1.3 {
246 SELECT count(*) FROM t1 GROUP BY y HAVING nth_value(x, 1) OVER (ORDER BY y);
247} {1 {misuse of window function nth_value()}}
248do_catchsql_test 7.1.4 {
249 SELECT count(*) FROM t1 GROUP BY nth_value(x, 1) OVER (ORDER BY y);
250} {1 {misuse of window function nth_value()}}
251do_catchsql_test 7.1.5 {
danc3163072018-06-23 19:29:56 +0000252 SELECT count(*) FROM t1 LIMIT nth_value(x, 1) OVER ();
dan26522d12018-06-11 18:16:51 +0000253} {1 {no such column: x}}
254do_catchsql_test 7.1.6 {
255 SELECT trim(x) OVER (ORDER BY y) FROM t1;
256} {1 {trim() may not be used as a window function}}
dan9a947222018-06-14 19:06:36 +0000257do_catchsql_test 7.1.7 {
258 SELECT max(x) OVER abc FROM t1 WINDOW def AS (ORDER BY y);
259} {1 {no such window: abc}}
260
dane0a5e202018-06-15 16:10:44 +0000261do_execsql_test 7.2 {
262 SELECT
263 lead(y) OVER win,
264 lead(y, 2) OVER win,
265 lead(y, 3, 'default') OVER win
266 FROM t1
267 WINDOW win AS (ORDER BY x)
268} {
269 4 6 8 6 8 10 8 10 default 10 {} default {} {} default
270}
271
dan13b08bb2018-06-15 20:46:12 +0000272do_execsql_test 7.3 {
273 SELECT row_number() OVER (ORDER BY x) FROM t1
274} {1 2 3 4 5}
275
dan660af932018-06-18 16:55:22 +0000276do_execsql_test 7.4 {
277 SELECT
278 row_number() OVER win,
279 lead(x) OVER win
280 FROM t1
281 WINDOW win AS (ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
282} {1 3 2 5 3 7 4 9 5 {}}
dane2f781b2018-05-17 19:24:08 +0000283
danc95f38d2018-06-18 20:34:43 +0000284#-------------------------------------------------------------------------
285# Attempt to use a window function in a view.
286#
287do_execsql_test 8.0 {
288 CREATE TABLE t3(a, b, c);
289
290 WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<6 )
291 INSERT INTO t3 SELECT i, i, i FROM s;
292
293 CREATE VIEW v1 AS SELECT
294 sum(b) OVER (ORDER BY c),
295 min(b) OVER (ORDER BY c),
296 max(b) OVER (ORDER BY c)
297 FROM t3;
298
299 CREATE VIEW v2 AS SELECT
300 sum(b) OVER win,
301 min(b) OVER win,
302 max(b) OVER win
303 FROM t3
304 WINDOW win AS (ORDER BY c);
305}
306
307do_execsql_test 8.1.1 {
308 SELECT * FROM v1
309} {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6}
310do_execsql_test 8.1.2 {
311 SELECT * FROM v2
312} {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6}
313
314db close
315sqlite3 db test.db
316do_execsql_test 8.2.1 {
317 SELECT * FROM v1
318} {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6}
319do_execsql_test 8.2.2 {
320 SELECT * FROM v2
321} {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6}
322
dan6fb2b542018-06-19 17:13:11 +0000323#-------------------------------------------------------------------------
324# Attempt to use a window function in a trigger.
325#
326do_execsql_test 9.0 {
327 CREATE TABLE t4(x, y);
328 INSERT INTO t4 VALUES(1, 'g');
329 INSERT INTO t4 VALUES(2, 'i');
330 INSERT INTO t4 VALUES(3, 'l');
331 INSERT INTO t4 VALUES(4, 'g');
332 INSERT INTO t4 VALUES(5, 'a');
333
334 CREATE TABLE t5(x, y, m);
335 CREATE TRIGGER t4i AFTER INSERT ON t4 BEGIN
336 DELETE FROM t5;
337 INSERT INTO t5
338 SELECT x, y, max(y) OVER xyz FROM t4
339 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x);
340 END;
341}
342
343do_execsql_test 9.1.1 {
344 SELECT x, y, max(y) OVER xyz FROM t4
345 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1
346} {1 g g 2 i i 3 l l 4 g i 5 a l}
347
348do_execsql_test 9.1.2 {
349 INSERT INTO t4 VALUES(6, 'm');
350 SELECT x, y, max(y) OVER xyz FROM t4
351 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1
352} {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m}
353
354do_execsql_test 9.1.3 {
355 SELECT * FROM t5 ORDER BY 1
356} {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m}
danc95f38d2018-06-18 20:34:43 +0000357
dancc464412018-06-19 18:11:05 +0000358do_execsql_test 9.2 {
359 WITH aaa(x, y, z) AS (
360 SELECT x, y, max(y) OVER xyz FROM t4
361 WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x)
362 )
363 SELECT * FROM aaa ORDER BY 1;
364} {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m}
365
366do_execsql_test 9.3 {
367 WITH aaa(x, y, z) AS (
368 SELECT x, y, max(y) OVER xyz FROM t4
369 WINDOW xyz AS (ORDER BY x)
370 )
371 SELECT *, min(z) OVER (ORDER BY x) FROM aaa ORDER BY 1;
372} {1 g g g 2 i i g 3 l l g 4 g l g 5 a l g 6 m m g}
danc95f38d2018-06-18 20:34:43 +0000373
dance103732018-06-23 07:59:39 +0000374#-------------------------------------------------------------------------
375#
376do_execsql_test 10.0 {
377 CREATE TABLE sales(emp TEXT PRIMARY KEY, region, total);
378 INSERT INTO sales VALUES
379 ('Alice', 'North', 34),
380 ('Frank', 'South', 22),
381 ('Charles', 'North', 45),
382 ('Darrell', 'South', 8),
383 ('Grant', 'South', 23),
384 ('Brad' , 'North', 22),
385 ('Elizabeth', 'South', 99),
386 ('Horace', 'East', 1);
387}
388
389# Best two salespeople from each region
390#
391do_execsql_test 10.1 {
392 SELECT emp, region, total FROM (
393 SELECT
394 emp, region, total,
395 row_number() OVER (PARTITION BY region ORDER BY total DESC) AS rank
396 FROM sales
397 ) WHERE rank<=2 ORDER BY region, total DESC
398} {
399 Horace East 1
400 Charles North 45
401 Alice North 34
402 Elizabeth South 99
403 Grant South 23
404}
405
danefa3a3c2018-06-23 16:26:20 +0000406do_execsql_test 10.2 {
407 SELECT emp, region, sum(total) OVER win FROM sales
408 WINDOW win AS (PARTITION BY region ORDER BY total)
409} {
410 Horace East 1
411 Brad North 22
412 Alice North 56
413 Charles North 101
414 Darrell South 8
415 Frank South 30
416 Grant South 53
417 Elizabeth South 152
418}
419
420do_execsql_test 10.3 {
421 SELECT emp, region, sum(total) OVER win FROM sales
422 WINDOW win AS (PARTITION BY region ORDER BY total)
423 LIMIT 5
424} {
425 Horace East 1
426 Brad North 22
427 Alice North 56
428 Charles North 101
429 Darrell South 8
430}
431
432do_execsql_test 10.4 {
433 SELECT emp, region, sum(total) OVER win FROM sales
434 WINDOW win AS (PARTITION BY region ORDER BY total)
435 LIMIT 5 OFFSET 2
436} {
437 Alice North 56
438 Charles North 101
439 Darrell South 8
440 Frank South 30
441 Grant South 53
442}
443
danc3163072018-06-23 19:29:56 +0000444do_execsql_test 10.5 {
445 SELECT emp, region, sum(total) OVER win FROM sales
446 WINDOW win AS (
447 PARTITION BY region ORDER BY total
448 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
449 )
450} {
451 Horace East 1
452 Brad North 101
453 Alice North 79
454 Charles North 45
455 Darrell South 152
456 Frank South 144
457 Grant South 122
458 Elizabeth South 99
459}
460
461do_execsql_test 10.6 {
462 SELECT emp, region, sum(total) OVER win FROM sales
463 WINDOW win AS (
464 PARTITION BY region ORDER BY total
465 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
466 ) LIMIT 5 OFFSET 2
467} {
468 Alice North 79
469 Charles North 45
470 Darrell South 152
471 Frank South 144
472 Grant South 122
473}
474
475do_execsql_test 10.7 {
476 SELECT emp, region, (
477 SELECT sum(total) OVER (
478 ORDER BY total RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
479 ) || outer.emp FROM sales
480 ) FROM sales AS outer;
481} {
482 Alice North 254Alice
483 Frank South 254Frank
484 Charles North 254Charles
485 Darrell South 254Darrell
486 Grant South 254Grant
487 Brad North 254Brad
488 Elizabeth South 254Elizabeth
489 Horace East 254Horace
490}
491
danc3163072018-06-23 19:29:56 +0000492do_execsql_test 10.8 {
493 SELECT emp, region, (
494 SELECT sum(total) FILTER (WHERE sales.emp!=outer.emp) OVER (
495 ORDER BY total RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
496 ) FROM sales
497 ) FROM sales AS outer;
498} {
499 Alice North 220
500 Frank South 232
501 Charles North 209
502 Darrell South 246
503 Grant South 231
504 Brad North 232
505 Elizabeth South 155
506 Horace East 253
507}
508
dan867be212018-06-25 11:42:08 +0000509#-------------------------------------------------------------------------
510# Check that it is not possible to use a window function in a CREATE INDEX
511# statement.
512#
513do_execsql_test 11.0 { CREATE TABLE t6(a, b, c); }
514
515do_catchsql_test 11.1 {
516 CREATE INDEX t6i ON t6(a) WHERE sum(b) OVER ();
517} {1 {misuse of window function sum()}}
518do_catchsql_test 11.2 {
519 CREATE INDEX t6i ON t6(a) WHERE lead(b) OVER ();
520} {1 {misuse of window function lead()}}
521
522do_catchsql_test 11.3 {
523 CREATE INDEX t6i ON t6(sum(b) OVER ());
524} {1 {misuse of window function sum()}}
525do_catchsql_test 11.4 {
526 CREATE INDEX t6i ON t6(lead(b) OVER ());
527} {1 {misuse of window function lead()}}
danc3163072018-06-23 19:29:56 +0000528
dan86fb6e12018-05-16 20:58:07 +0000529finish_test
dan26522d12018-06-11 18:16:51 +0000530