xref: /sqlite-3.40.0/test/windowfault.test (revision a92f9586)
1# 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 windowfault
17
18ifcapable !windowfunc {
19  finish_test
20  return
21}
22
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}
29faultsim_save_and_close
30
31do_faultsim_test 1 -start 1 -faults oom-t* -prep {
32  faultsim_restore_and_reopen
33} -body {
34  execsql {
35    SELECT row_number() OVER win,
36           rank() OVER win,
37           dense_rank() OVER win,
38           ntile(2) OVER win,
39           first_value(d) OVER win,
40           last_value(d) OVER win,
41           nth_value(d,2) OVER win,
42           lead(d) OVER win,
43           lag(d) OVER win,
44           max(d) OVER win,
45           min(d) OVER win
46    FROM t1
47    WINDOW win AS (ORDER BY a)
48  }
49} -test {
50  faultsim_test_result {0 {1 1 1 1 4 4 {} 8 {} 4 4 2 2 2 1 4 8 8 12 4 8 4 3 3 3 2 4 12 8 {} 8 12 4}}
51}
52
53do_faultsim_test 1.1 -faults oom-t* -prep {
54  faultsim_restore_and_reopen
55} -body {
56  execsql {
57    SELECT row_number() OVER win,
58           rank() OVER win,
59           dense_rank() OVER win
60    FROM t1
61    WINDOW win AS (PARTITION BY c<7 ORDER BY a)
62  }
63} -test {
64  faultsim_test_result {0 {1 1 1 2 2 2 1 1 1}}
65}
66
67do_faultsim_test 1.2 -faults oom-t* -prep {
68  faultsim_restore_and_reopen
69} -body {
70  execsql {
71    SELECT ntile(105)
72    OVER ( RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
73    FROM t1
74  }
75} -test {
76  faultsim_test_result {0 {1 2 3}}
77}
78
79do_faultsim_test 2 -start 1 -faults oom-* -prep {
80  faultsim_restore_and_reopen
81} -body {
82  execsql {
83    SELECT round(percent_rank() OVER win, 2),
84           round(cume_dist() OVER win, 2)
85    FROM t1
86    WINDOW win AS (ORDER BY a)
87  }
88} -test {
89  faultsim_test_result {0 {0.0 0.33 0.5 0.67 1.0 1.0}}
90}
91
92do_faultsim_test 3 -faults oom-* -prep {
93  faultsim_restore_and_reopen
94} -body {
95  execsql {
96    SELECT min(d) OVER win, max(d) OVER win
97    FROM t1
98    WINDOW win AS (ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
99  }
100} -test {
101  faultsim_test_result {0 {4 12 8 12 12 12}}
102}
103
104do_faultsim_test 4 -faults oom-* -prep {
105  faultsim_restore_and_reopen
106} -body {
107  execsql {
108    CREATE VIEW aaa AS
109    SELECT min(d) OVER w, max(d) OVER w
110    FROM t1
111    WINDOW w AS (ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING);
112    SELECT * FROM aaa;
113  }
114} -test {
115  faultsim_test_result {0 {4 12 8 12 12 12}}
116}
117
118do_faultsim_test 5 -start 1 -faults oom-* -prep {
119  faultsim_restore_and_reopen
120} -body {
121  execsql {
122    SELECT last_value(a) OVER win1,
123           last_value(a) OVER win2
124    FROM t1
125    WINDOW win1 AS (ORDER BY a ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING),
126           win2 AS (ORDER BY a)
127  }
128} -test {
129  faultsim_test_result {0 {5 1 9 5 9 9}}
130}
131
132do_faultsim_test 6 -faults oom-* -prep {
133  faultsim_restore_and_reopen
134} -body {
135  execsql {
136    SELECT percent_rank() OVER (), cume_dist() OVER () FROM t1
137  }
138} -test {
139  faultsim_test_result {0 {0.0 1.0 0.0 1.0 0.0 1.0}}
140}
141
142do_faultsim_test 7 -faults oom-* -prep {
143  faultsim_restore_and_reopen
144} -body {
145  execsql {
146    SELECT percent_rank() OVER (), cume_dist() OVER () FROM t1
147  }
148} -test {
149  faultsim_test_result {0 {0.0 1.0 0.0 1.0 0.0 1.0}}
150}
151
152do_faultsim_test 8 -faults oom-t* -prep {
153  faultsim_restore_and_reopen
154} -body {
155  execsql {
156    SELECT a, sum(b) OVER win1 FROM t1
157      WINDOW win1 AS (PARTITION BY a ),
158             win2 AS (PARTITION BY b )
159    ORDER BY a;
160  }
161} -test {
162  faultsim_test_result {0 {1 2 5 6 9 10}}
163}
164
165#-------------------------------------------------------------------------
166# The following test causes a cursor in REQURESEEK state to be passed
167# to sqlite3BtreeDelete(). An error is simulated within the seek operation
168# to restore the cursors position.
169#
170reset_db
171set big [string repeat x 900]
172do_execsql_test 9.0 {
173  PRAGMA page_size = 512;
174  PRAGMA cache_size = 2;
175  CREATE TABLE t(x INTEGER PRIMARY KEY, y TEXT);
176  WITH s(i) AS (
177    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1900
178  )
179  INSERT INTO t(y) SELECT $big FROM s;
180}
181db close
182
183testvfs tvfs -default 1
184tvfs script vfs_callback
185tvfs filter xRead
186
187sqlite3 db test.db
188proc vfs_callback {method file args} {
189  if {$file=="" && [info exists ::tmp_read_fail]} {
190    incr ::tmp_read_fail -1
191    if {$::tmp_read_fail<=0} {
192      return "SQLITE_IOERR"
193    }
194  }
195  return "SQLITE_OK"
196}
197
198set FAULTSIM(tmpread) [list                \
199  -injectstart   tmpread_injectstart       \
200  -injectstop    tmpread_injectstop        \
201  -injecterrlist {{1 {disk I/O error}}}    \
202]
203proc tmpread_injectstart {iFail} {
204  set ::tmp_read_fail $iFail
205}
206proc tmpread_injectstop {} {
207  set ret [expr $::tmp_read_fail<=0]
208  unset -nocomplain ::tmp_read_fail
209  return $ret
210}
211
212set L [db eval {SELECT 0.0 FROM t}]
213do_faultsim_test 9 -end 25 -faults tmpread -body {
214  execsql {
215    SELECT sum(y) OVER win FROM t
216    WINDOW win AS (
217      ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND 1800 FOLLOWING
218    )
219  }
220} -test {
221  faultsim_test_result [list 0 $::L]
222}
223
224catch {db close}
225tvfs delete
226
227reset_db
228do_execsql_test 10.0 {
229  CREATE TABLE t1(a, b, c, d);
230  CREATE TABLE t2(a, b, c, d);
231}
232
233do_faultsim_test 10 -faults oom* -prep {
234} -body {
235  execsql {
236    SELECT row_number() OVER win
237    FROM t1
238    WINDOW win AS (
239      ORDER BY (
240        SELECT percent_rank() OVER win2 FROM t2
241        WINDOW win2 AS (ORDER BY a)
242      )
243    )
244  }
245} -test {
246  faultsim_test_result {0 {}}
247}
248
249#-------------------------------------------------------------------------
250reset_db
251do_execsql_test 11.0 {
252  DROP TABLE IF EXISTS t0;
253  CREATE TABLE t0(c0 INTEGER UNIQUE);
254  INSERT INTO t0 VALUES(0);
255} {}
256
257do_faultsim_test 11.1 -faults oom* -prep {
258} -body {
259  execsql {
260    SELECT * FROM t0 WHERE
261      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
262  }
263} -test {
264  faultsim_test_result {0 {}}
265}
266
267do_faultsim_test 11.2 -faults oom* -prep {
268} -body {
269  execsql {
270    VALUES(false),(current_date collate binary)
271    intersect
272    values(count() not like group_concat(cast(cast(0e00 as text) as integer) <= NULL || 0.4e-0 || 0x8 & true ) over () collate rtrim);
273  }
274} -test {
275  faultsim_test_result {0 {}}
276}
277
278#-------------------------------------------------------------------------
279reset_db
280do_execsql_test 12.0 {
281  CREATE TABLE t1(a, b, c);
282} {}
283do_faultsim_test 12 -faults oom* -prep {
284} -body {
285  execsql {
286    WITH v(a, b, row_number) AS (
287      SELECT a, b, row_number() OVER (PARTITION BY a COLLATE nocase ORDER BY b) FROM t1
288    )
289    SELECT * FROM v WHERE a=2
290  }
291} -test {
292  faultsim_test_result {0 {}}
293}
294
295#-------------------------------------------------------------------------
296reset_db
297do_execsql_test 13.0 {
298  CREATE TABLE t1(id INTEGER PRIMARY KEY, a, b);
299  INSERT INTO t1 VALUES(1, '1', 'a');
300  INSERT INTO t1 VALUES(2, '22', 'b');
301  INSERT INTO t1 VALUES(3, '333', 'c');
302  INSERT INTO t1 VALUES(4, '4444', 'dddd');
303  INSERT INTO t1 VALUES(5, '55555', 'e');
304  INSERT INTO t1 VALUES(6, '666666', 'f');
305  INSERT INTO t1 VALUES(7, '7777777', 'gggggggggg');
306} {}
307
308set queryres [list {*}{
309  1b22
310  1b22c333
311  22c333dddd4444
312  333dddd4444e55555
313  4444e55555f666666
314  55555f666666gggggggggg7777777
315  666666gggggggggg7777777
316}]
317do_execsql_test 13.1 {
318  SELECT group_concat(a, b) OVER (
319    ORDER BY id RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
320  ) FROM t1
321} $queryres
322
323do_faultsim_test 13 -faults oom* -prep {
324} -body {
325  execsql {
326    SELECT group_concat(a, b) OVER (
327        ORDER BY id RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
328    ) FROM t1
329  }
330} -test {
331  faultsim_test_result [list 0 $::queryres]
332}
333
334finish_test
335