OLD | NEW |
| (Empty) |
1 # 2014 August 30 | |
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 # | |
12 | |
13 if {![info exists testdir]} { | |
14 set testdir [file join [file dirname [info script]] .. .. test] | |
15 } | |
16 source $testdir/tester.tcl | |
17 set ::testprefix rbu1 | |
18 | |
19 db close | |
20 sqlite3_shutdown | |
21 sqlite3_config_uri 1 | |
22 | |
23 # Create a simple RBU database. That expects to write to a table: | |
24 # | |
25 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
26 # | |
27 proc create_rbu1 {filename} { | |
28 forcedelete $filename | |
29 sqlite3 rbu1 $filename | |
30 rbu1 eval { | |
31 CREATE TABLE data_t1(a, b, c, rbu_control); | |
32 INSERT INTO data_t1 VALUES(1, 2, 3, 0); | |
33 INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); | |
34 INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0); | |
35 } | |
36 rbu1 close | |
37 return $filename | |
38 } | |
39 | |
40 # Create a simple RBU database. That expects to write to a table: | |
41 # | |
42 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
43 # | |
44 # This RBU includes both insert and delete operations. | |
45 # | |
46 proc create_rbu4 {filename} { | |
47 forcedelete $filename | |
48 sqlite3 rbu1 $filename | |
49 rbu1 eval { | |
50 CREATE TABLE data_t1(a, b, c, rbu_control); | |
51 INSERT INTO data_t1 VALUES(1, 2, 3, 0); | |
52 INSERT INTO data_t1 VALUES(2, NULL, 5, 1); | |
53 INSERT INTO data_t1 VALUES(3, 8, 9, 0); | |
54 INSERT INTO data_t1 VALUES(4, NULL, 11, 1); | |
55 } | |
56 rbu1 close | |
57 return $filename | |
58 } | |
59 # | |
60 # Create a simple RBU database. That expects to write to a table: | |
61 # | |
62 # CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); | |
63 # | |
64 # This RBU includes both insert and delete operations. | |
65 # | |
66 proc create_rbu4b {filename} { | |
67 forcedelete $filename | |
68 sqlite3 rbu1 $filename | |
69 rbu1 eval { | |
70 CREATE TABLE data_t1(c, b, '(a)', rbu_control); | |
71 INSERT INTO data_t1 VALUES(3, 2, 1, 0); | |
72 INSERT INTO data_t1 VALUES(5, NULL, 2, 1); | |
73 INSERT INTO data_t1 VALUES(9, 8, 3, 0); | |
74 INSERT INTO data_t1 VALUES(11, NULL, 4, 1); | |
75 } | |
76 rbu1 close | |
77 return $filename | |
78 } | |
79 | |
80 # Create a simple RBU database. That expects to write to a table: | |
81 # | |
82 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); | |
83 # | |
84 # This RBU includes update statements. | |
85 # | |
86 proc create_rbu5 {filename} { | |
87 forcedelete $filename | |
88 sqlite3 rbu5 $filename | |
89 rbu5 eval { | |
90 CREATE TABLE data_t1(a, b, c, d, rbu_control); | |
91 INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5 | |
92 INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5 | |
93 INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11 | |
94 } | |
95 rbu5 close | |
96 return $filename | |
97 } | |
98 | |
99 # Run the RBU in file $rbu on target database $target until completion. | |
100 # | |
101 proc run_rbu {target rbu} { | |
102 sqlite3rbu rbu $target $rbu | |
103 while 1 { | |
104 set rc [rbu step] | |
105 if {$rc!="SQLITE_OK"} break | |
106 } | |
107 rbu close | |
108 } | |
109 | |
110 proc step_rbu {target rbu} { | |
111 while 1 { | |
112 sqlite3rbu rbu $target $rbu | |
113 set rc [rbu step] | |
114 rbu close | |
115 if {$rc != "SQLITE_OK"} break | |
116 } | |
117 set rc | |
118 } | |
119 | |
120 # Same as [step_rbu], except using a URI to open the target db. | |
121 # | |
122 proc step_rbu_uri {target rbu} { | |
123 while 1 { | |
124 sqlite3rbu rbu file:$target?xyz=&abc=123 $rbu | |
125 set rc [rbu step] | |
126 rbu close | |
127 if {$rc != "SQLITE_OK"} break | |
128 } | |
129 set rc | |
130 } | |
131 | |
132 # Same as [step_rbu], except using an external state database - "state.db" | |
133 # | |
134 proc step_rbu_state {target rbu} { | |
135 while 1 { | |
136 sqlite3rbu rbu $target $rbu state.db | |
137 set rc [rbu step] | |
138 rbu close | |
139 if {$rc != "SQLITE_OK"} break | |
140 } | |
141 set rc | |
142 } | |
143 | |
144 proc dbfilecksum {file} { | |
145 sqlite3 ck $file | |
146 set cksum [dbcksum ck main] | |
147 ck close | |
148 set cksum | |
149 } | |
150 | |
151 foreach {tn3 create_vfs destroy_vfs} { | |
152 1 {} {} | |
153 2 { | |
154 sqlite3rbu_create_vfs -default myrbu "" | |
155 } { | |
156 sqlite3rbu_destroy_vfs myrbu | |
157 } | |
158 } { | |
159 | |
160 eval $create_vfs | |
161 | |
162 foreach {tn2 cmd} { | |
163 1 run_rbu | |
164 2 step_rbu 3 step_rbu_uri 4 step_rbu_state | |
165 } { | |
166 foreach {tn schema} { | |
167 1 { | |
168 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
169 } | |
170 2 { | |
171 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
172 CREATE INDEX i1 ON t1(b); | |
173 } | |
174 3 { | |
175 CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; | |
176 } | |
177 4 { | |
178 CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; | |
179 CREATE INDEX i1 ON t1(b); | |
180 } | |
181 5 { | |
182 CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) WITHOUT ROWID; | |
183 CREATE INDEX i1 ON t1(b); | |
184 } | |
185 6 { | |
186 CREATE TABLE t1(a, b, c, PRIMARY KEY(c)) WITHOUT ROWID; | |
187 CREATE INDEX i1 ON t1(b, a); | |
188 } | |
189 7 { | |
190 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
191 CREATE INDEX i1 ON t1(b, c); | |
192 CREATE INDEX i2 ON t1(c, b); | |
193 CREATE INDEX i3 ON t1(a, b, c, a, b, c); | |
194 } | |
195 | |
196 8 { | |
197 CREATE TABLE t1(a PRIMARY KEY, b, c); | |
198 CREATE INDEX i1 ON t1(b, c); | |
199 CREATE INDEX i2 ON t1(c, b); | |
200 CREATE INDEX i3 ON t1(a, b, c, a, b, c); | |
201 } | |
202 | |
203 9 { | |
204 CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)); | |
205 CREATE INDEX i1 ON t1(b); | |
206 } | |
207 | |
208 10 { | |
209 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
210 CREATE INDEX i1 ON t1(b DESC); | |
211 } | |
212 | |
213 11 { | |
214 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
215 CREATE INDEX i1 ON t1(b DESC, a ASC, c DESC); | |
216 } | |
217 | |
218 12 { | |
219 CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; | |
220 } | |
221 | |
222 13 { | |
223 CREATE TABLE t1(a INT, b, c, PRIMARY KEY(a DESC)) WITHOUT ROWID; | |
224 } | |
225 | |
226 14 { | |
227 CREATE TABLE t1(a, b, c, PRIMARY KEY(a DESC, c)) WITHOUT ROWID; | |
228 CREATE INDEX i1 ON t1(b); | |
229 } | |
230 | |
231 15 { | |
232 CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c DESC)) WITHOUT ROWID; | |
233 CREATE INDEX i1 ON t1(b); | |
234 } | |
235 | |
236 16 { | |
237 CREATE TABLE t1(a, b, c, PRIMARY KEY(c DESC, a)) WITHOUT ROWID; | |
238 CREATE INDEX i1 ON t1(b DESC, c, a); | |
239 } | |
240 } { | |
241 reset_db | |
242 execsql $schema | |
243 create_rbu1 rbu.db | |
244 set check [dbfilecksum rbu.db] | |
245 forcedelete state.db | |
246 | |
247 do_test $tn3.1.$tn2.$tn.1 { | |
248 $cmd test.db rbu.db | |
249 } {SQLITE_DONE} | |
250 | |
251 do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } { | |
252 1 2 3 | |
253 2 two three | |
254 3 {} 8.2 | |
255 } | |
256 do_execsql_test $tn3.1.$tn2.$tn.3 { SELECT * FROM t1 ORDER BY b ASC } { | |
257 3 {} 8.2 | |
258 1 2 3 | |
259 2 two three | |
260 } | |
261 do_execsql_test $tn3.1.$tn2.$tn.4 { SELECT * FROM t1 ORDER BY c ASC } { | |
262 1 2 3 | |
263 3 {} 8.2 | |
264 2 two three | |
265 } | |
266 | |
267 do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok | |
268 | |
269 if {$cmd=="step_rbu_state"} { | |
270 do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1 | |
271 do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 1 | |
272 } else { | |
273 do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0 | |
274 do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum rbu.db]} } 0 | |
275 } | |
276 } | |
277 } | |
278 | |
279 #------------------------------------------------------------------------- | |
280 # Check that an RBU cannot be applied to a table that has no PK. | |
281 # | |
282 # UPDATE: At one point RBU required that all tables featured either | |
283 # explicit IPK columns or were declared WITHOUT ROWID. This has been | |
284 # relaxed so that external PRIMARY KEYs on tables with automatic rowids | |
285 # are now allowed. | |
286 # | |
287 # UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed. | |
288 # However the input table must feature an "rbu_rowid" column. | |
289 # | |
290 reset_db | |
291 create_rbu1 rbu.db | |
292 do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) } | |
293 do_test $tn3.2.2 { | |
294 sqlite3rbu rbu test.db rbu.db | |
295 rbu step | |
296 } {SQLITE_ERROR} | |
297 do_test $tn3.2.3 { | |
298 list [catch { rbu close } msg] $msg | |
299 } {1 {SQLITE_ERROR - table data_t1 requires rbu_rowid column}} | |
300 reset_db | |
301 do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) } | |
302 do_test $tn3.2.5 { | |
303 sqlite3rbu rbu test.db rbu.db | |
304 rbu step | |
305 } {SQLITE_OK} | |
306 do_test $tn3.2.6 { | |
307 list [catch { rbu close } msg] $msg | |
308 } {0 SQLITE_OK} | |
309 | |
310 #------------------------------------------------------------------------- | |
311 # Check that if a UNIQUE constraint is violated the current and all | |
312 # subsequent [rbu step] calls return SQLITE_CONSTRAINT. And that the RBU | |
313 # transaction is rolled back by the [rbu close] that deletes the rbu | |
314 # handle. | |
315 # | |
316 foreach {tn errcode errmsg schema} { | |
317 1 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" { | |
318 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
319 INSERT INTO t1 VALUES(3, 2, 1); | |
320 } | |
321 | |
322 2 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" { | |
323 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE); | |
324 INSERT INTO t1 VALUES(4, 2, 'three'); | |
325 } | |
326 | |
327 3 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" { | |
328 CREATE TABLE t1(a PRIMARY KEY, b, c); | |
329 INSERT INTO t1 VALUES(3, 2, 1); | |
330 } | |
331 | |
332 4 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" { | |
333 CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE); | |
334 INSERT INTO t1 VALUES(4, 2, 'three'); | |
335 } | |
336 | |
337 } { | |
338 reset_db | |
339 execsql $schema | |
340 set cksum [dbcksum db main] | |
341 | |
342 do_test $tn3.3.$tn.1 { | |
343 create_rbu1 rbu.db | |
344 sqlite3rbu rbu test.db rbu.db | |
345 while {[set res [rbu step]]=="SQLITE_OK"} {} | |
346 set res | |
347 } $errcode | |
348 | |
349 do_test $tn3.3.$tn.2 { rbu step } $errcode | |
350 | |
351 do_test $tn3.3.$tn.3 { | |
352 list [catch { rbu close } msg] $msg | |
353 } [list 1 "$errcode - $errmsg"] | |
354 | |
355 do_test $tn3.3.$tn.4 { dbcksum db main } $cksum | |
356 } | |
357 | |
358 #------------------------------------------------------------------------- | |
359 # | |
360 foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state } { | |
361 foreach {tn schema} { | |
362 1 { | |
363 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
364 } | |
365 2 { | |
366 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
367 CREATE INDEX i1 ON t1(b); | |
368 } | |
369 3 { | |
370 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); | |
371 CREATE INDEX i1 ON t1(b); | |
372 CREATE INDEX i2 ON t1(c, b); | |
373 CREATE INDEX i3 ON t1(c, b, c); | |
374 } | |
375 4 { | |
376 CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID; | |
377 CREATE INDEX i1 ON t1(b); | |
378 CREATE INDEX i2 ON t1(c, b); | |
379 CREATE INDEX i3 ON t1(c, b, c); | |
380 } | |
381 5 { | |
382 CREATE TABLE t1(a INT PRIMARY KEY, b, c); | |
383 CREATE INDEX i1 ON t1(b); | |
384 CREATE INDEX i2 ON t1(c, b); | |
385 CREATE INDEX i3 ON t1(c, b, c); | |
386 } | |
387 | |
388 6 { | |
389 CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c); | |
390 CREATE INDEX i1 ON t1(b DESC); | |
391 CREATE INDEX i2 ON t1(c, b); | |
392 CREATE INDEX i3 ON t1(c DESC, b, c); | |
393 } | |
394 7 { | |
395 CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; | |
396 CREATE INDEX i1 ON t1(b); | |
397 CREATE INDEX i2 ON t1(c, b); | |
398 CREATE INDEX i3 ON t1(c, b, c); | |
399 } | |
400 } { | |
401 reset_db | |
402 execsql $schema | |
403 execsql { | |
404 INSERT INTO t1 VALUES(2, 'hello', 'world'); | |
405 INSERT INTO t1 VALUES(4, 'hello', 'planet'); | |
406 INSERT INTO t1 VALUES(6, 'hello', 'xyz'); | |
407 } | |
408 | |
409 create_rbu4 rbu.db | |
410 set check [dbfilecksum rbu.db] | |
411 forcedelete state.db | |
412 | |
413 do_test $tn3.4.$tn2.$tn.1 { | |
414 $cmd test.db rbu.db | |
415 } {SQLITE_DONE} | |
416 | |
417 do_execsql_test $tn3.4.$tn2.$tn.2 { | |
418 SELECT * FROM t1 ORDER BY a ASC; | |
419 } { | |
420 1 2 3 | |
421 3 8 9 | |
422 6 hello xyz | |
423 } | |
424 | |
425 do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok | |
426 | |
427 if {$cmd=="step_rbu_state"} { | |
428 do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1 | |
429 do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1 | |
430 } else { | |
431 do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0 | |
432 do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0 | |
433 } | |
434 } | |
435 } | |
436 | |
437 foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} { | |
438 foreach {tn schema} { | |
439 1 { | |
440 CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); | |
441 CREATE INDEX i1 ON t1(c, b); | |
442 } | |
443 2 { | |
444 CREATE TABLE t1(c, b, '(a)' PRIMARY KEY); | |
445 } | |
446 3 { | |
447 CREATE TABLE t1(c, b, '(a)' PRIMARY KEY) WITHOUT ROWID; | |
448 } | |
449 } { | |
450 reset_db | |
451 execsql $schema | |
452 execsql { | |
453 INSERT INTO t1('(a)', b, c) VALUES(2, 'hello', 'world'); | |
454 INSERT INTO t1('(a)', b, c) VALUES(4, 'hello', 'planet'); | |
455 INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz'); | |
456 } | |
457 | |
458 create_rbu4b rbu.db | |
459 set check [dbfilecksum rbu.db] | |
460 forcedelete state.db | |
461 | |
462 do_test $tn3.5.$tn2.$tn.1 { | |
463 $cmd test.db rbu.db | |
464 } {SQLITE_DONE} | |
465 | |
466 do_execsql_test $tn3.5.$tn2.$tn.2 { | |
467 SELECT * FROM t1 ORDER BY "(a)" ASC; | |
468 } { | |
469 3 2 1 | |
470 9 8 3 | |
471 xyz hello 6 | |
472 } | |
473 | |
474 do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok | |
475 | |
476 if {$cmd=="step_rbu_state"} { | |
477 do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1 | |
478 do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1 | |
479 } else { | |
480 do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0 | |
481 do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0 | |
482 } | |
483 } | |
484 } | |
485 | |
486 #------------------------------------------------------------------------- | |
487 # | |
488 foreach {tn2 cmd} {1 run_rbu 2 step_rbu 3 step_rbu_state} { | |
489 foreach {tn schema} { | |
490 1 { | |
491 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); | |
492 } | |
493 2 { | |
494 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); | |
495 CREATE INDEX i1 ON t1(d); | |
496 CREATE INDEX i2 ON t1(d, c); | |
497 CREATE INDEX i3 ON t1(d, c, b); | |
498 CREATE INDEX i4 ON t1(b); | |
499 CREATE INDEX i5 ON t1(c); | |
500 CREATE INDEX i6 ON t1(c, b); | |
501 } | |
502 3 { | |
503 CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID; | |
504 CREATE INDEX i1 ON t1(d); | |
505 CREATE INDEX i2 ON t1(d, c); | |
506 CREATE INDEX i3 ON t1(d, c, b); | |
507 CREATE INDEX i4 ON t1(b); | |
508 CREATE INDEX i5 ON t1(c); | |
509 CREATE INDEX i6 ON t1(c, b); | |
510 } | |
511 4 { | |
512 CREATE TABLE t1(a PRIMARY KEY, b, c, d); | |
513 CREATE INDEX i1 ON t1(d); | |
514 CREATE INDEX i2 ON t1(d, c); | |
515 CREATE INDEX i3 ON t1(d, c, b); | |
516 CREATE INDEX i4 ON t1(b); | |
517 CREATE INDEX i5 ON t1(c); | |
518 CREATE INDEX i6 ON t1(c, b); | |
519 } | |
520 } { | |
521 reset_db | |
522 execsql $schema | |
523 execsql { | |
524 INSERT INTO t1 VALUES(1, 2, 3, 4); | |
525 INSERT INTO t1 VALUES(2, 5, 6, 7); | |
526 INSERT INTO t1 VALUES(3, 8, 9, 10); | |
527 } | |
528 | |
529 create_rbu5 rbu.db | |
530 set check [dbfilecksum rbu.db] | |
531 forcedelete state.db | |
532 | |
533 do_test $tn3.5.$tn2.$tn.1 { | |
534 $cmd test.db rbu.db | |
535 } {SQLITE_DONE} | |
536 | |
537 do_execsql_test $tn3.5.$tn2.$tn.2 { | |
538 SELECT * FROM t1 ORDER BY a ASC; | |
539 } { | |
540 1 2 3 5 | |
541 2 5 10 5 | |
542 3 11 9 10 | |
543 } | |
544 | |
545 do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok | |
546 | |
547 if {$cmd=="step_rbu_state"} { | |
548 do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1 | |
549 do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum rbu.db]} } 1 | |
550 } else { | |
551 do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0 | |
552 do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum rbu.db]} } 0 | |
553 } | |
554 } | |
555 } | |
556 | |
557 #------------------------------------------------------------------------- | |
558 # Test some error cases: | |
559 # | |
560 # * A virtual table with no rbu_rowid column. | |
561 # * A no-PK table with no rbu_rowid column. | |
562 # * A PK table with an rbu_rowid column. | |
563 # | |
564 # 6: An update string of the wrong length | |
565 # | |
566 ifcapable fts3 { | |
567 foreach {tn schema error} { | |
568 1 { | |
569 CREATE TABLE t1(a, b); | |
570 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
571 } {SQLITE_ERROR - table data_t1 requires rbu_rowid column} | |
572 | |
573 2 { | |
574 CREATE VIRTUAL TABLE t1 USING fts4(a, b); | |
575 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
576 } {SQLITE_ERROR - table data_t1 requires rbu_rowid column} | |
577 | |
578 3 { | |
579 CREATE TABLE t1(a PRIMARY KEY, b); | |
580 CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control); | |
581 } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column} | |
582 | |
583 4 { | |
584 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); | |
585 CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control); | |
586 } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column} | |
587 | |
588 5 { | |
589 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; | |
590 CREATE TABLE rbu.data_t1(a, b, rbu_rowid, rbu_control); | |
591 } {SQLITE_ERROR - table data_t1 may not have rbu_rowid column} | |
592 | |
593 6 { | |
594 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; | |
595 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
596 INSERT INTO rbu.data_t1 VALUES(1, 2, 'x.x'); | |
597 } {SQLITE_ERROR - invalid rbu_control value} | |
598 | |
599 7 { | |
600 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; | |
601 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
602 INSERT INTO rbu.data_t1 VALUES(1, 2, NULL); | |
603 } {SQLITE_ERROR - invalid rbu_control value} | |
604 | |
605 8 { | |
606 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; | |
607 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
608 INSERT INTO rbu.data_t1 VALUES(1, 2, 4); | |
609 } {SQLITE_ERROR - invalid rbu_control value} | |
610 | |
611 9 { | |
612 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; | |
613 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
614 INSERT INTO rbu.data_t1 VALUES(1, 2, 2); | |
615 } {SQLITE_ERROR - invalid rbu_control value} | |
616 | |
617 10 { | |
618 CREATE TABLE t2(a, b); | |
619 CREATE TABLE rbu.data_t1(a, b, rbu_control); | |
620 INSERT INTO rbu.data_t1 VALUES(1, 2, 2); | |
621 } {SQLITE_ERROR - no such table: t1} | |
622 | |
623 11 { | |
624 CREATE TABLE rbu.data_t2(a, b, rbu_control); | |
625 INSERT INTO rbu.data_t2 VALUES(1, 2, 2); | |
626 } {SQLITE_ERROR - no such table: t2} | |
627 | |
628 } { | |
629 reset_db | |
630 forcedelete rbu.db | |
631 execsql { ATTACH 'rbu.db' AS rbu } | |
632 execsql $schema | |
633 | |
634 do_test $tn3.7.$tn { | |
635 list [catch { run_rbu test.db rbu.db } msg] $msg | |
636 } [list 1 $error] | |
637 } | |
638 } | |
639 | |
640 # Test that an RBU database containing no input tables is handled | |
641 # correctly. | |
642 reset_db | |
643 forcedelete rbu.db | |
644 do_test $tn3.8 { | |
645 list [catch { run_rbu test.db rbu.db } msg] $msg | |
646 } {0 SQLITE_DONE} | |
647 | |
648 # Test that RBU can update indexes containing NULL values. | |
649 # | |
650 reset_db | |
651 forcedelete rbu.db | |
652 do_execsql_test $tn3.9.1 { | |
653 CREATE TABLE t1(a PRIMARY KEY, b, c); | |
654 CREATE INDEX i1 ON t1(b, c); | |
655 INSERT INTO t1 VALUES(1, 1, NULL); | |
656 INSERT INTO t1 VALUES(2, NULL, 2); | |
657 INSERT INTO t1 VALUES(3, NULL, NULL); | |
658 | |
659 ATTACH 'rbu.db' AS rbu; | |
660 CREATE TABLE rbu.data_t1(a, b, c, rbu_control); | |
661 INSERT INTO data_t1 VALUES(1, NULL, NULL, 1); | |
662 INSERT INTO data_t1 VALUES(3, NULL, NULL, 1); | |
663 } {} | |
664 | |
665 do_test $tn3.9.2 { | |
666 list [catch { run_rbu test.db rbu.db } msg] $msg | |
667 } {0 SQLITE_DONE} | |
668 | |
669 do_execsql_test $tn3.9.3 { | |
670 SELECT * FROM t1 | |
671 } {2 {} 2} | |
672 do_execsql_test $tn3.9.4 { PRAGMA integrity_check } {ok} | |
673 | |
674 catch { db close } | |
675 eval $destroy_vfs | |
676 } | |
677 | |
678 | |
679 finish_test | |
680 | |
OLD | NEW |