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