3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #*************************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this script is testing the incremental merge function.
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
17 source $testdir/fts3_common.tcl
19 # If SQLITE_ENABLE_FTS3 is defined, omit this file.
25 proc fts3_integrity_check {tbl} {
26 db eval "INSERT INTO $tbl ($tbl) VALUES('integrity-check')"
30 foreach mod {fts3 fts4} {
31 set ::testprefix fts4merge-$mod
34 #-------------------------------------------------------------------------
37 do_test 1.0 { fts3_build_db_1 -module $mod 1004 } {}
38 do_test 1.1 { fts3_integrity_check t1 } {ok}
40 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
42 0 {0 1 2 3 4 5 6 7 8 9 10 11}
43 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
47 for {set i 0} {$i<20} {incr i} {
48 do_execsql_test 1.2.$i.1 { INSERT INTO t1(t1) VALUES('merge=1') }
49 do_test 1.2.$i.2 { fts3_integrity_check t1 } ok
50 do_execsql_test 1.2.$i.3 {
51 SELECT docid FROM t1 WHERE t1 MATCH 'zero one two three'
52 } {123 132 213 231 312 321}
56 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
61 for {set i 0} {$i<100} {incr i} {
62 do_execsql_test 1.4.$i { INSERT INTO t1(t1) VALUES('merge=1,4') }
63 do_test 1.4.$i.2 { fts3_integrity_check t1 } ok
64 do_execsql_test 1.4.$i.3 {
65 SELECT docid FROM t1 WHERE t1 MATCH 'zero one two three'
66 } {123 132 213 231 312 321}
70 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
75 #-------------------------------------------------------------------------
76 # Test cases 2.* test that errors in the xxx part of the 'merge=xxx' are
79 do_execsql_test 2.0 "CREATE VIRTUAL TABLE t2 USING $mod"
90 do_catchsql_test 2.$tn {
91 INSERT INTO t2(t2) VALUES($arg);
92 } {1 {SQL logic error}}
95 #-------------------------------------------------------------------------
100 execsql { PRAGMA page_size = 512 }
101 fts3_build_db_2 -module $mod 30040
103 do_test 3.1 { fts3_integrity_check t2 } {ok}
105 do_execsql_test 3.2 {
106 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
114 do_execsql_test 3.3 {
115 INSERT INTO t2(t2) VALUES('merge=1000000,2');
116 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
121 #-------------------------------------------------------------------------
125 do_execsql_test 4.1 "
126 PRAGMA page_size = 512;
127 CREATE VIRTUAL TABLE t4 USING $mod;
128 PRAGMA main.page_size;
132 foreach x {a c b d e f g h i j k l m n o p} {
133 execsql "INSERT INTO t4 VALUES('[string repeat $x 600]')"
135 execsql {SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level}
136 } {0 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15}}
138 foreach {tn expect} {
139 1 "0 {0 1 2 3 4 5 6 7 8 9 10 11 12 13} 1 0"
140 2 "0 {0 1 2 3 4 5 6 7 8 9 10 11 12} 1 0"
141 3 "0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0"
142 4 "0 {0 1 2 3 4 5 6 7 8 9 10} 1 0"
143 5 "0 {0 1 2 3 4 5 6 7 8 9} 1 0"
144 6 "0 {0 1 2 3 4 5 6 7 8} 1 0"
145 7 "0 {0 1 2 3 4 5 6 7} 1 0"
146 8 "0 {0 1 2 3 4 5 6} 1 0"
147 9 "0 {0 1 2 3 4 5} 1 0"
149 do_execsql_test 4.3.$tn {
150 INSERT INTO t4(t4) VALUES('merge=1,16');
151 SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level;
155 do_execsql_test 4.4.1 {
156 SELECT quote(value) FROM t4_stat WHERE rowid=1
159 do_execsql_test 4.4.2 {
160 DELETE FROM t4_stat WHERE rowid=1;
161 INSERT INTO t4(t4) VALUES('merge=1,12');
162 SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level;
163 } "0 {0 1 2 3 4 5} 1 0"
166 #-------------------------------------------------------------------------
169 # Test that if a crisis-merge occurs that disrupts an ongoing incremental
170 # merge, the next call to "merge=A,B" identifies this and starts a new
171 # incremental merge. There are two scenarios:
173 # * There are less segments on the input level that the disrupted
174 # incremental merge operated on, or
176 # * Sufficient segments exist on the input level but the segments
177 # contain keys smaller than the largest key in the potential output
182 fts3_build_db_1 -module $mod 1000
185 do_execsql_test 5.2 {
186 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
189 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
193 do_execsql_test 5.3 {
194 INSERT INTO t1(t1) VALUES('merge=1,5');
195 INSERT INTO t1(t1) VALUES('merge=1,5');
196 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
198 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14}
202 do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
204 foreach docid [execsql {SELECT docid FROM t1}] {
205 execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
209 do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'010F'}
211 do_execsql_test 5.7 {
212 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
213 SELECT quote(value) from t1_stat WHERE rowid=1;
216 1 {0 1 2 3 4 5 6 7 8 9 10 11 12}
221 do_execsql_test 5.8 {
222 INSERT INTO t1(t1) VALUES('merge=1,6');
223 INSERT INTO t1(t1) VALUES('merge=1,6');
224 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
225 SELECT quote(value) from t1_stat WHERE rowid=1;
227 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
228 2 {0 1 2 3 4 5 6 7 8} X'010E'
231 do_test 5.8.1 { fts3_integrity_check t1 } ok
234 set L [expr 16*16*7 + 16*3 + 12]
235 foreach docid [execsql {
236 SELECT docid FROM t1 UNION ALL SELECT docid FROM t1 LIMIT $L
238 execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
242 do_execsql_test 5.10 {
243 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
244 SELECT quote(value) from t1_stat WHERE rowid=1;
246 0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0 2 0 3 0 X'010E'
249 do_execsql_test 5.11 {
250 INSERT INTO t1(t1) VALUES('merge=1,6');
251 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
252 SELECT quote(value) from t1_stat WHERE rowid=1;
254 1 {0 1} 2 0 3 0 X'010E'
257 #-------------------------------------------------------------------------
260 # At one point the following test caused an assert() to fail (because the
261 # second 'merge=1,2' operation below actually "merges" a single input
262 # segment, which was unexpected).
266 set a [string repeat a 900]
267 set b [string repeat b 900]
268 set c [string repeat c 900]
269 set d [string repeat d 900]
271 execsql "CREATE VIRTUAL TABLE t1 USING $mod"
274 INSERT INTO t1 VALUES($a);
275 INSERT INTO t1 VALUES($b);
278 INSERT INTO t1 VALUES($c);
279 INSERT INTO t1 VALUES($d);
284 INSERT INTO t1(t1) VALUES('merge=1,2');
285 INSERT INTO t1(t1) VALUES('merge=1,2');
289 #-------------------------------------------------------------------------
292 # Test that the value returned by sqlite3_total_changes() increases by
293 # 1 following a no-op "merge=A,B", or by more than 1 if actual work is
298 fts3_build_db_1 -module $mod 1000
301 do_execsql_test 7.1 {
302 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
305 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
309 set x [db total_changes]
310 execsql { INSERT INTO t1(t1) VALUES('merge=2,10') }
311 expr { ([db total_changes] - $x)>1 }
314 set x [db total_changes]
315 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
316 expr { ([db total_changes] - $x)>1 }
319 set x [db total_changes]
320 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
321 expr { ([db total_changes] - $x)>1 }
324 set x [db total_changes]
325 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
326 expr { ([db total_changes] - $x)>1 }