|
1 # 2001 September 15 |
|
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. The |
|
12 # focus of this file is testing the 'progress callback'. |
|
13 # |
|
14 # $Id: progress.test,v 1.8 2007/06/15 14:53:53 danielk1977 Exp $ |
|
15 |
|
16 set testdir [file dirname $argv0] |
|
17 source $testdir/tester.tcl |
|
18 |
|
19 # If the progress callback is not available in this build, skip this |
|
20 # whole file. |
|
21 ifcapable !progress { |
|
22 finish_test |
|
23 return |
|
24 } |
|
25 |
|
26 # Build some test data |
|
27 # |
|
28 execsql { |
|
29 BEGIN; |
|
30 CREATE TABLE t1(a); |
|
31 INSERT INTO t1 VALUES(1); |
|
32 INSERT INTO t1 VALUES(2); |
|
33 INSERT INTO t1 VALUES(3); |
|
34 INSERT INTO t1 VALUES(4); |
|
35 INSERT INTO t1 VALUES(5); |
|
36 INSERT INTO t1 VALUES(6); |
|
37 INSERT INTO t1 VALUES(7); |
|
38 INSERT INTO t1 VALUES(8); |
|
39 INSERT INTO t1 VALUES(9); |
|
40 INSERT INTO t1 VALUES(10); |
|
41 COMMIT; |
|
42 } |
|
43 |
|
44 |
|
45 # Test that the progress callback is invoked. |
|
46 do_test progress-1.0 { |
|
47 set counter 0 |
|
48 db progress 1 "[namespace code {incr counter}] ; expr 0" |
|
49 execsql { |
|
50 SELECT * FROM t1 |
|
51 } |
|
52 expr $counter > 1 |
|
53 } 1 |
|
54 do_test progress-1.0.1 { |
|
55 db progress |
|
56 } {::namespace inscope :: {incr counter} ; expr 0} |
|
57 do_test progress-1.0.2 { |
|
58 set v [catch {db progress xyz bogus} msg] |
|
59 lappend v $msg |
|
60 } {1 {expected integer but got "xyz"}} |
|
61 |
|
62 # Test that the query is abandoned when the progress callback returns non-zero |
|
63 do_test progress-1.1 { |
|
64 set counter 0 |
|
65 db progress 1 "[namespace code {incr counter}] ; expr 1" |
|
66 set rc [catch {execsql { |
|
67 SELECT * FROM t1 |
|
68 }}] |
|
69 list $counter $rc |
|
70 } {1 1} |
|
71 |
|
72 # Test that the query is rolled back when the progress callback returns |
|
73 # non-zero. |
|
74 do_test progress-1.2 { |
|
75 |
|
76 # This figures out how many opcodes it takes to copy 5 extra rows into t1. |
|
77 db progress 1 "[namespace code {incr five_rows}] ; expr 0" |
|
78 set five_rows 0 |
|
79 execsql { |
|
80 INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 6 |
|
81 } |
|
82 db progress 0 "" |
|
83 execsql { |
|
84 DELETE FROM t1 WHERE a > 10 |
|
85 } |
|
86 |
|
87 # Now set up the progress callback to abandon the query after the number of |
|
88 # opcodes to copy 5 rows. That way, when we try to copy 6 rows, we know |
|
89 # some data will have been inserted into the table by the time the progress |
|
90 # callback abandons the query. |
|
91 db progress $five_rows "expr 1" |
|
92 catchsql { |
|
93 INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 9 |
|
94 } |
|
95 execsql { |
|
96 SELECT count(*) FROM t1 |
|
97 } |
|
98 } 10 |
|
99 |
|
100 # Test that an active transaction remains active and not rolled back |
|
101 # after the progress query abandons a query. |
|
102 # |
|
103 # UPDATE: It is now recognised that this is a sure route to database |
|
104 # corruption. So the transaction is rolled back. |
|
105 do_test progress-1.3 { |
|
106 |
|
107 db progress 0 "" |
|
108 execsql BEGIN |
|
109 execsql { |
|
110 INSERT INTO t1 VALUES(11) |
|
111 } |
|
112 db progress 1 "expr 1" |
|
113 catchsql { |
|
114 INSERT INTO t1 VALUES(12) |
|
115 } |
|
116 db progress 0 "" |
|
117 catchsql COMMIT |
|
118 } {1 {cannot commit - no transaction is active}} |
|
119 do_test progress-1.3.1 { |
|
120 execsql { |
|
121 SELECT count(*) FROM t1 |
|
122 } |
|
123 } 10 |
|
124 |
|
125 # Check that a value of 0 for N means no progress callback |
|
126 do_test progress-1.4 { |
|
127 set counter 0 |
|
128 db progress 0 "[namespace code {incr counter}] ; expr 0" |
|
129 execsql { |
|
130 SELECT * FROM t1; |
|
131 } |
|
132 set counter |
|
133 } 0 |
|
134 |
|
135 db progress 0 "" |
|
136 |
|
137 # Make sure other queries can be run from within the progress |
|
138 # handler. Ticket #1827 |
|
139 # |
|
140 do_test progress-1.5 { |
|
141 set rx 0 |
|
142 proc set_rx {args} { |
|
143 db progress 0 {} |
|
144 set ::rx [db eval {SELECT count(*) FROM t1}] |
|
145 return [expr 0] |
|
146 } |
|
147 db progress 10 set_rx |
|
148 db eval { |
|
149 SELECT sum(a) FROM t1 |
|
150 } |
|
151 } {55} |
|
152 do_test progress-1.6 { |
|
153 set ::rx |
|
154 } {10} |
|
155 |
|
156 # Check that abandoning a query using the progress handler does |
|
157 # not cause other queries to abort. Ticket #2415. |
|
158 do_test progress-1.7 { |
|
159 execsql { |
|
160 CREATE TABLE abc(a, b, c); |
|
161 INSERT INTO abc VALUES(1, 2, 3); |
|
162 INSERT INTO abc VALUES(4, 5, 6); |
|
163 INSERT INTO abc VALUES(7, 8, 9); |
|
164 } |
|
165 |
|
166 set ::res [list] |
|
167 db eval {SELECT a, b, c FROM abc} { |
|
168 lappend ::res $a $b $c |
|
169 db progress 10 "expr 1" |
|
170 catch {db eval {SELECT a, b, c FROM abc} { }} msg |
|
171 lappend ::res $msg |
|
172 } |
|
173 |
|
174 set ::res |
|
175 } {1 2 3 interrupted 4 5 6 interrupted 7 8 9 interrupted} |
|
176 |
|
177 finish_test |