blob: 41f91fdc8f562a1c6f911e107cdde73583b0c491 [file] [log] [blame]
dan593c9822012-03-08 18:39:03 +00001# 2012 March 06
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 script is testing the incremental merge function.
13#
14
15set testdir [file dirname $argv0]
16source $testdir/tester.tcl
17source $testdir/fts3_common.tcl
dan593c9822012-03-08 18:39:03 +000018
19# If SQLITE_ENABLE_FTS3 is defined, omit this file.
20ifcapable !fts3 {
21 finish_test
22 return
23}
24
dancbcd9f52012-03-26 10:36:55 +000025proc fts3_integrity_check {tbl} {
26 db eval "INSERT INTO $tbl ($tbl) VALUES('integrity-check')"
27 return "ok"
28}
29
dan311ec022012-03-27 15:00:06 +000030foreach mod {fts3 fts4} {
31 set ::testprefix fts4merge-$mod
dan5730ef52012-03-14 20:01:52 +000032 reset_db
dan5730ef52012-03-14 20:01:52 +000033
dan311ec022012-03-27 15:00:06 +000034 #-------------------------------------------------------------------------
35 # Test cases 1.*
36 #
37 do_test 1.0 { fts3_build_db_1 -module $mod 1004 } {}
38 do_test 1.1 { fts3_integrity_check t1 } {ok}
39 do_execsql_test 1.1 {
40 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
41 } {
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}
44 2 {0 1 2}
dane81eaec2012-03-22 16:48:12 +000045 }
dan311ec022012-03-27 15:00:06 +000046
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}
53 }
54
55 do_execsql_test 1.3 {
56 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
57 } {
58 0 {0 1 2 3}
59 1 {0 1 2 3 4 5 6}
60 2 {0 1 2 3}
61 }
62
63 for {set i 0} {$i<100} {incr i} {
64 do_execsql_test 1.4.$i { INSERT INTO t1(t1) VALUES('merge=1,4') }
65 do_test 1.4.$i.2 { fts3_integrity_check t1 } ok
66 do_execsql_test 1.4.$i.3 {
67 SELECT docid FROM t1 WHERE t1 MATCH 'zero one two three'
68 } {123 132 213 231 312 321}
69 }
70
71 do_execsql_test 1.5 {
72 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
73 } {
74 2 {0 1}
75 3 0
76 }
77
78 #-------------------------------------------------------------------------
79 # Test cases 2.* test that errors in the xxx part of the 'merge=xxx' are
80 # handled correctly.
81 #
82 do_execsql_test 2.0 "CREATE VIRTUAL TABLE t2 USING $mod"
83
84 foreach {tn arg} {
85 1 {merge=abc}
86 2 {merge=%%%}
87 3 {merge=,}
88 4 {merge=5,}
89 5 {merge=6,%}
90 6 {merge=6,six}
91 7 {merge=6,1}
dan311ec022012-03-27 15:00:06 +000092 } {
93 do_catchsql_test 2.$tn {
94 INSERT INTO t2(t2) VALUES($arg);
95 } {1 {SQL logic error or missing database}}
96 }
97
98 #-------------------------------------------------------------------------
99 # Test cases 3.*
100 #
101 do_test 3.0 {
102 reset_db
103 execsql { PRAGMA page_size = 512 }
104 fts3_build_db_2 -module $mod 30040
105 } {}
106 do_test 3.1 { fts3_integrity_check t2 } {ok}
107
108 do_execsql_test 3.2 {
109 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
110 } {
111 0 {0 1 2 3 4 5 6}
112 1 {0 1 2 3 4}
113 2 {0 1 2 3 4}
114 3 {0 1 2 3 4 5 6}
115 }
116
117 do_execsql_test 3.3 {
118 INSERT INTO t2(t2) VALUES('merge=1000000,2');
119 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level
120 } {
121 0 0
122 2 0
123 3 0
124 4 0
125 6 0
126 }
127
128 #-------------------------------------------------------------------------
129 # Test cases 4.*
130 #
131 reset_db
132 do_execsql_test 4.1 "
133 PRAGMA page_size = 512;
134 CREATE VIRTUAL TABLE t4 USING $mod;
135 PRAGMA main.page_size;
136 " {512}
137
138 do_test 4.2 {
139 foreach x {a c b d e f g h i j k l m n o p} {
140 execsql "INSERT INTO t4 VALUES('[string repeat $x 600]')"
141 }
142 execsql {SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level}
143 } {0 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15}}
144
145 foreach {tn expect} {
146 1 "0 {0 1 2 3 4 5 6 7 8 9 10 11 12 13} 1 0"
147 2 "0 {0 1 2 3 4 5 6 7 8 9 10 11 12} 1 0"
148 3 "0 {0 1 2 3 4 5 6 7 8 9 10 11} 1 0"
149 4 "0 {0 1 2 3 4 5 6 7 8 9 10} 1 0"
150 5 "0 {0 1 2 3 4 5 6 7 8 9} 1 0"
151 6 "0 {0 1 2 3 4 5 6 7 8} 1 0"
152 7 "0 {0 1 2 3 4 5 6 7} 1 0"
153 8 "0 {0 1 2 3 4 5 6} 1 0"
154 9 "0 {0 1 2 3 4 5} 1 0"
155 } {
156 do_execsql_test 4.3.$tn {
157 INSERT INTO t4(t4) VALUES('merge=1,16');
158 SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level;
159 } $expect
160 }
161
162 do_execsql_test 4.4.1 {
163 SELECT quote(value) FROM t4_stat WHERE rowid=1
164 } {X'0006'}
165
166 do_execsql_test 4.4.2 {
167 DELETE FROM t4_stat WHERE rowid=1;
168 INSERT INTO t4(t4) VALUES('merge=1,12');
dane81eaec2012-03-22 16:48:12 +0000169 SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level;
dan311ec022012-03-27 15:00:06 +0000170 } "0 {0 1 2 3 4 5} 1 0"
171
172
173 #-------------------------------------------------------------------------
174 # Test cases 5.*
175 #
176 # Test that if a crisis-merge occurs that disrupts an ongoing incremental
177 # merge, the next call to "merge=A,B" identifies this and starts a new
178 # incremental merge. There are two scenarios:
179 #
180 # * There are less segments on the input level that the disrupted
181 # incremental merge operated on, or
182 #
183 # * Sufficient segments exist on the input level but the segments
184 # contain keys smaller than the largest key in the potential output
185 # segment.
186 #
187 do_test 5.1 {
188 reset_db
189 fts3_build_db_1 -module $mod 1000
190 } {}
191
192 do_execsql_test 5.2 {
193 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
194 } {
195 0 {0 1 2 3 4 5 6 7}
196 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
197 2 {0 1 2}
dan185c1fb2012-03-22 17:48:00 +0000198 }
dan311ec022012-03-27 15:00:06 +0000199
200 do_execsql_test 5.3 {
201 INSERT INTO t1(t1) VALUES('merge=1,5');
202 INSERT INTO t1(t1) VALUES('merge=1,5');
203 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
204 } {
205 0 {0 1 2}
206 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14}
207 2 {0 1 2 3}
dan185c1fb2012-03-22 17:48:00 +0000208 }
dan311ec022012-03-27 15:00:06 +0000209
210 do_execsql_test 5.4 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
211 do_test 5.5 {
212 foreach docid [execsql {SELECT docid FROM t1}] {
213 execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
214 }
215 } {}
216
217 do_execsql_test 5.6 {SELECT quote(value) from t1_stat WHERE rowid=1} {X'0105'}
218
219 do_execsql_test 5.7 {
220 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
221 SELECT quote(value) from t1_stat WHERE rowid=1;
222 } {
223 0 {0 1 2 3 4 5 6 7 8 9 10}
224 1 {0 1 2 3 4 5 6 7 8 9 10 11 12}
225 2 {0 1 2 3 4 5 6 7}
226 X'0105'
dan3501a912012-03-23 14:38:49 +0000227 }
dan311ec022012-03-27 15:00:06 +0000228
229 do_execsql_test 5.8 {
230 INSERT INTO t1(t1) VALUES('merge=1,6');
231 INSERT INTO t1(t1) VALUES('merge=1,6');
232 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
233 SELECT quote(value) from t1_stat WHERE rowid=1;
234 } {
235 0 {0 1 2 3 4}
236 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
237 2 {0 1 2 3 4 5 6 7 8} X'0106'
dan3501a912012-03-23 14:38:49 +0000238 }
dan311ec022012-03-27 15:00:06 +0000239
240 do_test 5.8.1 { fts3_integrity_check t1 } ok
241
242 do_test 5.9 {
243 set L [expr 16*16*7 + 16*3 + 12]
244 foreach docid [execsql {
245 SELECT docid FROM t1 UNION ALL SELECT docid FROM t1 LIMIT $L
246 }] {
247 execsql {INSERT INTO t1 SELECT * FROM t1 WHERE docid=$docid}
248 }
249 } {}
250
251 do_execsql_test 5.10 {
252 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
253 SELECT quote(value) from t1_stat WHERE rowid=1;
254 } {
255 0 0 1 {0 1} 2 0 3 0 X'0106'
256 }
257
258 do_execsql_test 5.11 {
259 INSERT INTO t1(t1) VALUES('merge=1,6');
260 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level;
261 SELECT quote(value) from t1_stat WHERE rowid=1;
262 } {
263 0 0 1 {0 1} 2 0 3 0 X''
264 }
265
266 #-------------------------------------------------------------------------
267 # Test cases 6.*
268 #
269 # At one point the following test caused an assert() to fail (because the
270 # second 'merge=1,2' operation below actually "merges" a single input
271 # segment, which was unexpected).
272 #
273 do_test 6.1 {
274 reset_db
275 set a [string repeat a 900]
276 set b [string repeat b 900]
277 set c [string repeat c 900]
278 set d [string repeat d 900]
dane81eaec2012-03-22 16:48:12 +0000279
dan311ec022012-03-27 15:00:06 +0000280 execsql "CREATE VIRTUAL TABLE t1 USING $mod"
281 execsql {
282 BEGIN;
283 INSERT INTO t1 VALUES($a);
284 INSERT INTO t1 VALUES($b);
285 COMMIT;
286 BEGIN;
287 INSERT INTO t1 VALUES($c);
288 INSERT INTO t1 VALUES($d);
289 COMMIT;
290 }
291
292 execsql {
293 INSERT INTO t1(t1) VALUES('merge=1,2');
294 INSERT INTO t1(t1) VALUES('merge=1,2');
295 }
296 } {}
297
298 #-------------------------------------------------------------------------
299 # Test cases 7.*
300 #
301 # Test that the value returned by sqlite3_total_changes() increases by
302 # 1 following a no-op "merge=A,B", or by more than 1 if actual work is
303 # performed.
304 #
305 do_test 7.0 {
306 reset_db
307 fts3_build_db_1 -module $mod 1000
308 } {}
309
310 do_execsql_test 7.1 {
311 SELECT level, group_concat(idx, ' ') FROM t1_segdir GROUP BY level
312 } {
313 0 {0 1 2 3 4 5 6 7}
314 1 {0 1 2 3 4 5 6 7 8 9 10 11 12 13}
315 2 {0 1 2}
316 }
317 do_test 7.2 {
318 set x [db total_changes]
319 execsql { INSERT INTO t1(t1) VALUES('merge=2,10') }
320 expr { ([db total_changes] - $x)>1 }
321 } {1}
322 do_test 7.3 {
323 set x [db total_changes]
324 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
325 expr { ([db total_changes] - $x)>1 }
326 } {1}
327 do_test 7.4 {
328 set x [db total_changes]
329 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
330 expr { ([db total_changes] - $x)>1 }
331 } {0}
332 do_test 7.5 {
333 set x [db total_changes]
334 execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
335 expr { ([db total_changes] - $x)>1 }
336 } {0}
danba512b02012-03-23 15:38:43 +0000337
danba512b02012-03-23 15:38:43 +0000338}
danba512b02012-03-23 15:38:43 +0000339
dane81eaec2012-03-22 16:48:12 +0000340finish_test