| OLD | NEW |
| (Empty) |
| 1 # 2008 December 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 # | |
| 12 # $Id: savepoint.test,v 1.13 2009/07/18 08:30:45 danielk1977 Exp $ | |
| 13 | |
| 14 set testdir [file dirname $argv0] | |
| 15 source $testdir/tester.tcl | |
| 16 | |
| 17 | |
| 18 #---------------------------------------------------------------------- | |
| 19 # The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE | |
| 20 # and ROLLBACK TO comands are correctly parsed, and that the auto-commit | |
| 21 # flag is correctly set and unset as a result. | |
| 22 # | |
| 23 do_test savepoint-1.1 { | |
| 24 execsql { | |
| 25 SAVEPOINT sp1; | |
| 26 RELEASE sp1; | |
| 27 } | |
| 28 } {} | |
| 29 do_test savepoint-1.2 { | |
| 30 execsql { | |
| 31 SAVEPOINT sp1; | |
| 32 ROLLBACK TO sp1; | |
| 33 } | |
| 34 } {} | |
| 35 do_test savepoint-1.3 { | |
| 36 execsql { SAVEPOINT sp1 } | |
| 37 db close | |
| 38 } {} | |
| 39 sqlite3 db test.db | |
| 40 do_test savepoint-1.4.1 { | |
| 41 execsql { | |
| 42 SAVEPOINT sp1; | |
| 43 SAVEPOINT sp2; | |
| 44 RELEASE sp1; | |
| 45 } | |
| 46 sqlite3_get_autocommit db | |
| 47 } {1} | |
| 48 do_test savepoint-1.4.2 { | |
| 49 execsql { | |
| 50 SAVEPOINT sp1; | |
| 51 SAVEPOINT sp2; | |
| 52 RELEASE sp2; | |
| 53 } | |
| 54 sqlite3_get_autocommit db | |
| 55 } {0} | |
| 56 do_test savepoint-1.4.3 { | |
| 57 execsql { RELEASE sp1 } | |
| 58 sqlite3_get_autocommit db | |
| 59 } {1} | |
| 60 do_test savepoint-1.4.4 { | |
| 61 execsql { | |
| 62 SAVEPOINT sp1; | |
| 63 SAVEPOINT sp2; | |
| 64 ROLLBACK TO sp1; | |
| 65 } | |
| 66 sqlite3_get_autocommit db | |
| 67 } {0} | |
| 68 do_test savepoint-1.4.5 { | |
| 69 execsql { RELEASE SAVEPOINT sp1 } | |
| 70 sqlite3_get_autocommit db | |
| 71 } {1} | |
| 72 do_test savepoint-1.4.6 { | |
| 73 execsql { | |
| 74 SAVEPOINT sp1; | |
| 75 SAVEPOINT sp2; | |
| 76 SAVEPOINT sp3; | |
| 77 ROLLBACK TO SAVEPOINT sp3; | |
| 78 ROLLBACK TRANSACTION TO sp2; | |
| 79 ROLLBACK TRANSACTION TO SAVEPOINT sp1; | |
| 80 } | |
| 81 sqlite3_get_autocommit db | |
| 82 } {0} | |
| 83 do_test savepoint-1.4.7 { | |
| 84 execsql { RELEASE SAVEPOINT SP1 } | |
| 85 sqlite3_get_autocommit db | |
| 86 } {1} | |
| 87 do_test savepoint-1.5 { | |
| 88 execsql { | |
| 89 SAVEPOINT sp1; | |
| 90 ROLLBACK TO sp1; | |
| 91 } | |
| 92 } {} | |
| 93 do_test savepoint-1.6 { | |
| 94 execsql COMMIT | |
| 95 } {} | |
| 96 | |
| 97 #------------------------------------------------------------------------ | |
| 98 # These tests - savepoint-2.* - test rollbacks and releases of savepoints | |
| 99 # with a very simple data set. | |
| 100 # | |
| 101 | |
| 102 do_test savepoint-2.1 { | |
| 103 execsql { | |
| 104 CREATE TABLE t1(a, b, c); | |
| 105 BEGIN; | |
| 106 INSERT INTO t1 VALUES(1, 2, 3); | |
| 107 SAVEPOINT one; | |
| 108 UPDATE t1 SET a = 2, b = 3, c = 4; | |
| 109 } | |
| 110 execsql { SELECT * FROM t1 } | |
| 111 } {2 3 4} | |
| 112 do_test savepoint-2.2 { | |
| 113 execsql { | |
| 114 ROLLBACK TO one; | |
| 115 } | |
| 116 execsql { SELECT * FROM t1 } | |
| 117 } {1 2 3} | |
| 118 do_test savepoint-2.3 { | |
| 119 execsql { | |
| 120 INSERT INTO t1 VALUES(4, 5, 6); | |
| 121 } | |
| 122 execsql { SELECT * FROM t1 } | |
| 123 } {1 2 3 4 5 6} | |
| 124 do_test savepoint-2.4 { | |
| 125 execsql { | |
| 126 ROLLBACK TO one; | |
| 127 } | |
| 128 execsql { SELECT * FROM t1 } | |
| 129 } {1 2 3} | |
| 130 | |
| 131 | |
| 132 do_test savepoint-2.5 { | |
| 133 execsql { | |
| 134 INSERT INTO t1 VALUES(7, 8, 9); | |
| 135 SAVEPOINT two; | |
| 136 INSERT INTO t1 VALUES(10, 11, 12); | |
| 137 } | |
| 138 execsql { SELECT * FROM t1 } | |
| 139 } {1 2 3 7 8 9 10 11 12} | |
| 140 do_test savepoint-2.6 { | |
| 141 execsql { | |
| 142 ROLLBACK TO two; | |
| 143 } | |
| 144 execsql { SELECT * FROM t1 } | |
| 145 } {1 2 3 7 8 9} | |
| 146 do_test savepoint-2.7 { | |
| 147 execsql { | |
| 148 INSERT INTO t1 VALUES(10, 11, 12); | |
| 149 } | |
| 150 execsql { SELECT * FROM t1 } | |
| 151 } {1 2 3 7 8 9 10 11 12} | |
| 152 do_test savepoint-2.8 { | |
| 153 execsql { | |
| 154 ROLLBACK TO one; | |
| 155 } | |
| 156 execsql { SELECT * FROM t1 } | |
| 157 } {1 2 3} | |
| 158 do_test savepoint-2.9 { | |
| 159 execsql { | |
| 160 INSERT INTO t1 VALUES('a', 'b', 'c'); | |
| 161 SAVEPOINT two; | |
| 162 INSERT INTO t1 VALUES('d', 'e', 'f'); | |
| 163 } | |
| 164 execsql { SELECT * FROM t1 } | |
| 165 } {1 2 3 a b c d e f} | |
| 166 do_test savepoint-2.10 { | |
| 167 execsql { | |
| 168 RELEASE two; | |
| 169 } | |
| 170 execsql { SELECT * FROM t1 } | |
| 171 } {1 2 3 a b c d e f} | |
| 172 do_test savepoint-2.11 { | |
| 173 execsql { | |
| 174 ROLLBACK; | |
| 175 } | |
| 176 execsql { SELECT * FROM t1 } | |
| 177 } {} | |
| 178 | |
| 179 #------------------------------------------------------------------------ | |
| 180 # This block of tests - savepoint-3.* - test that when a transaction | |
| 181 # savepoint is rolled back, locks are not released from database files. | |
| 182 # And that when a transaction savepoint is released, they are released. | |
| 183 # | |
| 184 do_test savepoint-3.1 { | |
| 185 execsql { SAVEPOINT "transaction" } | |
| 186 execsql { PRAGMA lock_status } | |
| 187 } {main unlocked temp closed} | |
| 188 | |
| 189 do_test savepoint-3.2 { | |
| 190 execsql { INSERT INTO t1 VALUES(1, 2, 3) } | |
| 191 execsql { PRAGMA lock_status } | |
| 192 } {main reserved temp closed} | |
| 193 | |
| 194 do_test savepoint-3.3 { | |
| 195 execsql { ROLLBACK TO "transaction" } | |
| 196 execsql { PRAGMA lock_status } | |
| 197 } {main reserved temp closed} | |
| 198 | |
| 199 do_test savepoint-3.4 { | |
| 200 execsql { INSERT INTO t1 VALUES(1, 2, 3) } | |
| 201 execsql { PRAGMA lock_status } | |
| 202 } {main reserved temp closed} | |
| 203 | |
| 204 do_test savepoint-3.5 { | |
| 205 execsql { RELEASE "transaction" } | |
| 206 execsql { PRAGMA lock_status } | |
| 207 } {main unlocked temp closed} | |
| 208 | |
| 209 #------------------------------------------------------------------------ | |
| 210 # Test that savepoints that include schema modifications are handled | |
| 211 # correctly. Test cases savepoint-4.*. | |
| 212 # | |
| 213 do_test savepoint-4.1 { | |
| 214 execsql { | |
| 215 CREATE TABLE t2(d, e, f); | |
| 216 SELECT sql FROM sqlite_master; | |
| 217 } | |
| 218 } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}} | |
| 219 do_test savepoint-4.2 { | |
| 220 execsql { | |
| 221 BEGIN; | |
| 222 CREATE TABLE t3(g,h); | |
| 223 INSERT INTO t3 VALUES('I', 'II'); | |
| 224 SAVEPOINT one; | |
| 225 DROP TABLE t3; | |
| 226 } | |
| 227 } {} | |
| 228 do_test savepoint-4.3 { | |
| 229 execsql { | |
| 230 CREATE TABLE t3(g, h, i); | |
| 231 INSERT INTO t3 VALUES('III', 'IV', 'V'); | |
| 232 } | |
| 233 execsql {SELECT * FROM t3} | |
| 234 } {III IV V} | |
| 235 do_test savepoint-4.4 { | |
| 236 execsql { ROLLBACK TO one; } | |
| 237 execsql {SELECT * FROM t3} | |
| 238 } {I II} | |
| 239 do_test savepoint-4.5 { | |
| 240 execsql { | |
| 241 ROLLBACK; | |
| 242 SELECT sql FROM sqlite_master; | |
| 243 } | |
| 244 } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}} | |
| 245 | |
| 246 do_test savepoint-4.6 { | |
| 247 execsql { | |
| 248 BEGIN; | |
| 249 INSERT INTO t1 VALUES('o', 't', 't'); | |
| 250 SAVEPOINT sp1; | |
| 251 CREATE TABLE t3(a, b, c); | |
| 252 INSERT INTO t3 VALUES('z', 'y', 'x'); | |
| 253 } | |
| 254 execsql {SELECT * FROM t3} | |
| 255 } {z y x} | |
| 256 do_test savepoint-4.7 { | |
| 257 execsql { | |
| 258 ROLLBACK TO sp1; | |
| 259 CREATE TABLE t3(a); | |
| 260 INSERT INTO t3 VALUES('value'); | |
| 261 } | |
| 262 execsql {SELECT * FROM t3} | |
| 263 } {value} | |
| 264 do_test savepoint-4.8 { | |
| 265 execsql COMMIT | |
| 266 } {} | |
| 267 | |
| 268 #------------------------------------------------------------------------ | |
| 269 # Test some logic errors to do with the savepoint feature. | |
| 270 # | |
| 271 | |
| 272 ifcapable incrblob { | |
| 273 do_test savepoint-5.1.1 { | |
| 274 execsql { | |
| 275 CREATE TABLE blobs(x); | |
| 276 INSERT INTO blobs VALUES('a twentyeight character blob'); | |
| 277 } | |
| 278 set fd [db incrblob blobs x 1] | |
| 279 puts -nonewline $fd "hello" | |
| 280 catchsql {SAVEPOINT abc} | |
| 281 } {1 {cannot open savepoint - SQL statements in progress}} | |
| 282 do_test savepoint-5.1.2 { | |
| 283 close $fd | |
| 284 catchsql {SAVEPOINT abc} | |
| 285 } {0 {}} | |
| 286 | |
| 287 do_test savepoint-5.2 { | |
| 288 execsql {RELEASE abc} | |
| 289 catchsql {RELEASE abc} | |
| 290 } {1 {no such savepoint: abc}} | |
| 291 | |
| 292 do_test savepoint-5.3.1 { | |
| 293 execsql {SAVEPOINT abc} | |
| 294 catchsql {ROLLBACK TO def} | |
| 295 } {1 {no such savepoint: def}} | |
| 296 do_test savepoint-5.3.2 { | |
| 297 execsql {SAVEPOINT def} | |
| 298 set fd [db incrblob -readonly blobs x 1] | |
| 299 catchsql {ROLLBACK TO def} | |
| 300 } {1 {cannot rollback savepoint - SQL statements in progress}} | |
| 301 do_test savepoint-5.3.3 { | |
| 302 catchsql {RELEASE def} | |
| 303 } {0 {}} | |
| 304 do_test savepoint-5.3.4 { | |
| 305 close $fd | |
| 306 execsql {savepoint def} | |
| 307 set fd [db incrblob blobs x 1] | |
| 308 catchsql {release def} | |
| 309 } {1 {cannot release savepoint - SQL statements in progress}} | |
| 310 do_test savepoint-5.3.5 { | |
| 311 close $fd | |
| 312 execsql {release abc} | |
| 313 } {} | |
| 314 | |
| 315 do_test savepoint-5.4.1 { | |
| 316 execsql { | |
| 317 SAVEPOINT main; | |
| 318 INSERT INTO blobs VALUES('another blob'); | |
| 319 } | |
| 320 } {} | |
| 321 do_test savepoint-5.4.2 { | |
| 322 sqlite3 db2 test.db | |
| 323 execsql { BEGIN ; SELECT * FROM blobs } db2 | |
| 324 catchsql { RELEASE main } | |
| 325 } {1 {database is locked}} | |
| 326 do_test savepoint-5.4.3 { | |
| 327 db2 close | |
| 328 catchsql { RELEASE main } | |
| 329 } {0 {}} | |
| 330 do_test savepoint-5.4.4 { | |
| 331 execsql { SELECT x FROM blobs WHERE rowid = 2 } | |
| 332 } {{another blob}} | |
| 333 } | |
| 334 | |
| 335 #------------------------------------------------------------------------- | |
| 336 # The following tests, savepoint-6.*, test an incr-vacuum inside of a | |
| 337 # couple of nested savepoints. | |
| 338 # | |
| 339 ifcapable {autovacuum && pragma} { | |
| 340 db close | |
| 341 file delete -force test.db | |
| 342 sqlite3 db test.db | |
| 343 | |
| 344 do_test savepoint-6.1 { | |
| 345 execsql { | |
| 346 PRAGMA auto_vacuum = incremental; | |
| 347 CREATE TABLE t1(a, b, c); | |
| 348 CREATE INDEX i1 ON t1(a, b); | |
| 349 BEGIN; | |
| 350 INSERT INTO t1 VALUES(randstr(10,400),randstr(10,400),randstr(10,400)); | |
| 351 } | |
| 352 set r "randstr(10,400)" | |
| 353 for {set ii 0} {$ii < 10} {incr ii} { | |
| 354 execsql "INSERT INTO t1 SELECT $r, $r, $r FROM t1" | |
| 355 } | |
| 356 execsql { COMMIT } | |
| 357 } {} | |
| 358 | |
| 359 integrity_check savepoint-6.2 | |
| 360 | |
| 361 do_test savepoint-6.3 { | |
| 362 execsql { | |
| 363 PRAGMA cache_size = 10; | |
| 364 BEGIN; | |
| 365 UPDATE t1 SET a = randstr(10,10) WHERE (rowid%4)==0; | |
| 366 SAVEPOINT one; | |
| 367 DELETE FROM t1 WHERE rowid%2; | |
| 368 PRAGMA incr_vacuum; | |
| 369 SAVEPOINT two; | |
| 370 INSERT INTO t1 SELECT randstr(10,400), randstr(10,400), c FROM t1; | |
| 371 DELETE FROM t1 WHERE rowid%2; | |
| 372 PRAGMA incr_vacuum; | |
| 373 ROLLBACK TO one; | |
| 374 COMMIT; | |
| 375 } | |
| 376 } {} | |
| 377 | |
| 378 integrity_check savepoint-6.4 | |
| 379 } | |
| 380 | |
| 381 #------------------------------------------------------------------------- | |
| 382 # The following tests, savepoint-7.*, attempt to break the logic | |
| 383 # surrounding savepoints by growing and shrinking the database file. | |
| 384 # | |
| 385 db close | |
| 386 file delete -force test.db | |
| 387 sqlite3 db test.db | |
| 388 | |
| 389 do_test savepoint-7.1 { | |
| 390 execsql { | |
| 391 PRAGMA auto_vacuum = incremental; | |
| 392 PRAGMA cache_size = 10; | |
| 393 BEGIN; | |
| 394 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 395 INSERT INTO t1(a) VALUES('alligator'); | |
| 396 INSERT INTO t1(a) VALUES('angelfish'); | |
| 397 INSERT INTO t1(a) VALUES('ant'); | |
| 398 INSERT INTO t1(a) VALUES('antelope'); | |
| 399 INSERT INTO t1(a) VALUES('ape'); | |
| 400 INSERT INTO t1(a) VALUES('baboon'); | |
| 401 INSERT INTO t1(a) VALUES('badger'); | |
| 402 INSERT INTO t1(a) VALUES('bear'); | |
| 403 INSERT INTO t1(a) VALUES('beetle'); | |
| 404 INSERT INTO t1(a) VALUES('bird'); | |
| 405 INSERT INTO t1(a) VALUES('bison'); | |
| 406 UPDATE t1 SET b = randstr(1000,1000); | |
| 407 UPDATE t1 SET b = b||randstr(1000,1000); | |
| 408 UPDATE t1 SET b = b||randstr(1000,1000); | |
| 409 UPDATE t1 SET b = b||randstr(10,1000); | |
| 410 COMMIT; | |
| 411 } | |
| 412 expr ([execsql { PRAGMA page_count }] > 20) | |
| 413 } {1} | |
| 414 do_test savepoint-7.2.1 { | |
| 415 execsql { | |
| 416 BEGIN; | |
| 417 SAVEPOINT one; | |
| 418 CREATE TABLE t2(a, b); | |
| 419 INSERT INTO t2 SELECT a, b FROM t1; | |
| 420 ROLLBACK TO one; | |
| 421 } | |
| 422 execsql { | |
| 423 PRAGMA integrity_check; | |
| 424 } | |
| 425 } {ok} | |
| 426 do_test savepoint-7.2.2 { | |
| 427 execsql { | |
| 428 COMMIT; | |
| 429 PRAGMA integrity_check; | |
| 430 } | |
| 431 } {ok} | |
| 432 | |
| 433 do_test savepoint-7.3.1 { | |
| 434 execsql { | |
| 435 CREATE TABLE t2(a, b); | |
| 436 INSERT INTO t2 SELECT a, b FROM t1; | |
| 437 } | |
| 438 } {} | |
| 439 do_test savepoint-7.3.2 { | |
| 440 execsql { | |
| 441 BEGIN; | |
| 442 SAVEPOINT one; | |
| 443 DELETE FROM t2; | |
| 444 PRAGMA incremental_vacuum; | |
| 445 SAVEPOINT two; | |
| 446 INSERT INTO t2 SELECT a, b FROM t1; | |
| 447 ROLLBACK TO two; | |
| 448 COMMIT; | |
| 449 } | |
| 450 execsql { PRAGMA integrity_check } | |
| 451 } {ok} | |
| 452 | |
| 453 do_test savepoint-7.4.1 { | |
| 454 db close | |
| 455 file delete -force test.db | |
| 456 sqlite3 db test.db | |
| 457 execsql { | |
| 458 PRAGMA auto_vacuum = incremental; | |
| 459 CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); | |
| 460 INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000)); | |
| 461 BEGIN; | |
| 462 DELETE FROM t1; | |
| 463 SAVEPOINT one; | |
| 464 PRAGMA incremental_vacuum; | |
| 465 ROLLBACK TO one; | |
| 466 COMMIT; | |
| 467 } | |
| 468 | |
| 469 execsql { PRAGMA integrity_check } | |
| 470 } {ok} | |
| 471 | |
| 472 do_test savepoint-7.5.1 { | |
| 473 execsql { | |
| 474 PRAGMA incremental_vacuum; | |
| 475 CREATE TABLE t5(x, y); | |
| 476 INSERT INTO t5 VALUES(1, randstr(1000,1000)); | |
| 477 INSERT INTO t5 VALUES(2, randstr(1000,1000)); | |
| 478 INSERT INTO t5 VALUES(3, randstr(1000,1000)); | |
| 479 | |
| 480 BEGIN; | |
| 481 INSERT INTO t5 VALUES(4, randstr(1000,1000)); | |
| 482 INSERT INTO t5 VALUES(5, randstr(1000,1000)); | |
| 483 DELETE FROM t5 WHERE x=1 OR x=2; | |
| 484 SAVEPOINT one; | |
| 485 PRAGMA incremental_vacuum; | |
| 486 SAVEPOINT two; | |
| 487 INSERT INTO t5 VALUES(1, randstr(1000,1000)); | |
| 488 INSERT INTO t5 VALUES(2, randstr(1000,1000)); | |
| 489 ROLLBACK TO two; | |
| 490 ROLLBACK TO one; | |
| 491 COMMIT; | |
| 492 PRAGMA integrity_check; | |
| 493 } | |
| 494 } {ok} | |
| 495 do_test savepoint-7.5.2 { | |
| 496 execsql { | |
| 497 DROP TABLE t5; | |
| 498 } | |
| 499 } {} | |
| 500 | |
| 501 # Test oddly named and quoted savepoints. | |
| 502 # | |
| 503 do_test savepoint-8-1 { | |
| 504 execsql { SAVEPOINT "save1" } | |
| 505 execsql { RELEASE save1 } | |
| 506 } {} | |
| 507 do_test savepoint-8-2 { | |
| 508 execsql { SAVEPOINT "Including whitespace " } | |
| 509 execsql { RELEASE "including Whitespace " } | |
| 510 } {} | |
| 511 | |
| 512 # Test that the authorization callback works. | |
| 513 # | |
| 514 ifcapable auth { | |
| 515 proc auth {args} { | |
| 516 eval lappend ::authdata $args | |
| 517 return SQLITE_OK | |
| 518 } | |
| 519 db auth auth | |
| 520 | |
| 521 do_test savepoint-9.1 { | |
| 522 set ::authdata [list] | |
| 523 execsql { SAVEPOINT sp1 } | |
| 524 set ::authdata | |
| 525 } {SQLITE_SAVEPOINT BEGIN sp1 {} {}} | |
| 526 do_test savepoint-9.2 { | |
| 527 set ::authdata [list] | |
| 528 execsql { ROLLBACK TO sp1 } | |
| 529 set ::authdata | |
| 530 } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {}} | |
| 531 do_test savepoint-9.3 { | |
| 532 set ::authdata [list] | |
| 533 execsql { RELEASE sp1 } | |
| 534 set ::authdata | |
| 535 } {SQLITE_SAVEPOINT RELEASE sp1 {} {}} | |
| 536 | |
| 537 proc auth {args} { | |
| 538 eval lappend ::authdata $args | |
| 539 return SQLITE_DENY | |
| 540 } | |
| 541 db auth auth | |
| 542 | |
| 543 do_test savepoint-9.4 { | |
| 544 set ::authdata [list] | |
| 545 set res [catchsql { SAVEPOINT sp1 }] | |
| 546 concat $::authdata $res | |
| 547 } {SQLITE_SAVEPOINT BEGIN sp1 {} {} 1 {not authorized}} | |
| 548 do_test savepoint-9.5 { | |
| 549 set ::authdata [list] | |
| 550 set res [catchsql { ROLLBACK TO sp1 }] | |
| 551 concat $::authdata $res | |
| 552 } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {} 1 {not authorized}} | |
| 553 do_test savepoint-9.6 { | |
| 554 set ::authdata [list] | |
| 555 set res [catchsql { RELEASE sp1 }] | |
| 556 concat $::authdata $res | |
| 557 } {SQLITE_SAVEPOINT RELEASE sp1 {} {} 1 {not authorized}} | |
| 558 | |
| 559 catch { db eval ROLLBACK } | |
| 560 db auth "" | |
| 561 } | |
| 562 | |
| 563 #------------------------------------------------------------------------- | |
| 564 # The following tests - savepoint-10.* - test the interaction of | |
| 565 # savepoints and ATTACH statements. | |
| 566 # | |
| 567 | |
| 568 # First make sure it is not possible to attach or detach a database while | |
| 569 # a savepoint is open (it is not possible if any transaction is open). | |
| 570 # | |
| 571 do_test savepoint-10.1.1 { | |
| 572 catchsql { | |
| 573 SAVEPOINT one; | |
| 574 ATTACH 'test2.db' AS aux; | |
| 575 } | |
| 576 } {1 {cannot ATTACH database within transaction}} | |
| 577 do_test savepoint-10.1.2 { | |
| 578 execsql { | |
| 579 RELEASE one; | |
| 580 ATTACH 'test2.db' AS aux; | |
| 581 } | |
| 582 catchsql { | |
| 583 SAVEPOINT one; | |
| 584 DETACH aux; | |
| 585 } | |
| 586 } {1 {cannot DETACH database within transaction}} | |
| 587 do_test savepoint-10.1.3 { | |
| 588 execsql { | |
| 589 RELEASE one; | |
| 590 DETACH aux; | |
| 591 } | |
| 592 } {} | |
| 593 | |
| 594 # The lock state of the TEMP database can vary if SQLITE_TEMP_STORE=3 | |
| 595 # And the following set of tests is only really interested in the status | |
| 596 # of the aux1 and aux2 locks. So record the current lock status of | |
| 597 # TEMP for use in the answers. | |
| 598 set templockstate [lindex [db eval {PRAGMA lock_status}] 3] | |
| 599 | |
| 600 | |
| 601 do_test savepoint-10.2.1 { | |
| 602 file delete -force test3.db | |
| 603 file delete -force test2.db | |
| 604 execsql { | |
| 605 ATTACH 'test2.db' AS aux1; | |
| 606 ATTACH 'test3.db' AS aux2; | |
| 607 DROP TABLE t1; | |
| 608 CREATE TABLE main.t1(x, y); | |
| 609 CREATE TABLE aux1.t2(x, y); | |
| 610 CREATE TABLE aux2.t3(x, y); | |
| 611 SELECT name FROM sqlite_master | |
| 612 UNION ALL | |
| 613 SELECT name FROM aux1.sqlite_master | |
| 614 UNION ALL | |
| 615 SELECT name FROM aux2.sqlite_master; | |
| 616 } | |
| 617 } {t1 t2 t3} | |
| 618 do_test savepoint-10.2.2 { | |
| 619 execsql { PRAGMA lock_status } | |
| 620 } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] | |
| 621 | |
| 622 do_test savepoint-10.2.3 { | |
| 623 execsql { | |
| 624 SAVEPOINT one; | |
| 625 INSERT INTO t1 VALUES(1, 2); | |
| 626 PRAGMA lock_status; | |
| 627 } | |
| 628 } [list main reserved temp $templockstate aux1 unlocked aux2 unlocked] | |
| 629 do_test savepoint-10.2.4 { | |
| 630 execsql { | |
| 631 INSERT INTO t3 VALUES(3, 4); | |
| 632 PRAGMA lock_status; | |
| 633 } | |
| 634 } [list main reserved temp $templockstate aux1 unlocked aux2 reserved] | |
| 635 do_test savepoint-10.2.5 { | |
| 636 execsql { | |
| 637 SAVEPOINT two; | |
| 638 INSERT INTO t2 VALUES(5, 6); | |
| 639 PRAGMA lock_status; | |
| 640 } | |
| 641 } [list main reserved temp $templockstate aux1 reserved aux2 reserved] | |
| 642 do_test savepoint-10.2.6 { | |
| 643 execsql { SELECT * FROM t2 } | |
| 644 } {5 6} | |
| 645 do_test savepoint-10.2.7 { | |
| 646 execsql { ROLLBACK TO two } | |
| 647 execsql { SELECT * FROM t2 } | |
| 648 } {} | |
| 649 do_test savepoint-10.2.8 { | |
| 650 execsql { PRAGMA lock_status } | |
| 651 } [list main reserved temp $templockstate aux1 reserved aux2 reserved] | |
| 652 do_test savepoint-10.2.9 { | |
| 653 execsql { SELECT 'a', * FROM t1 UNION ALL SELECT 'b', * FROM t3 } | |
| 654 } {a 1 2 b 3 4} | |
| 655 do_test savepoint-10.2.9 { | |
| 656 execsql { | |
| 657 INSERT INTO t2 VALUES(5, 6); | |
| 658 RELEASE one; | |
| 659 } | |
| 660 execsql { | |
| 661 SELECT * FROM t1; | |
| 662 SELECT * FROM t2; | |
| 663 SELECT * FROM t3; | |
| 664 } | |
| 665 } {1 2 5 6 3 4} | |
| 666 do_test savepoint-10.2.9 { | |
| 667 execsql { PRAGMA lock_status } | |
| 668 } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] | |
| 669 | |
| 670 do_test savepoint-10.2.10 { | |
| 671 execsql { | |
| 672 SAVEPOINT one; | |
| 673 INSERT INTO t1 VALUES('a', 'b'); | |
| 674 SAVEPOINT two; | |
| 675 INSERT INTO t2 VALUES('c', 'd'); | |
| 676 SAVEPOINT three; | |
| 677 INSERT INTO t3 VALUES('e', 'f'); | |
| 678 } | |
| 679 execsql { | |
| 680 SELECT * FROM t1; | |
| 681 SELECT * FROM t2; | |
| 682 SELECT * FROM t3; | |
| 683 } | |
| 684 } {1 2 a b 5 6 c d 3 4 e f} | |
| 685 do_test savepoint-10.2.11 { | |
| 686 execsql { ROLLBACK TO two } | |
| 687 execsql { | |
| 688 SELECT * FROM t1; | |
| 689 SELECT * FROM t2; | |
| 690 SELECT * FROM t3; | |
| 691 } | |
| 692 } {1 2 a b 5 6 3 4} | |
| 693 do_test savepoint-10.2.12 { | |
| 694 execsql { | |
| 695 INSERT INTO t3 VALUES('g', 'h'); | |
| 696 ROLLBACK TO two; | |
| 697 } | |
| 698 execsql { | |
| 699 SELECT * FROM t1; | |
| 700 SELECT * FROM t2; | |
| 701 SELECT * FROM t3; | |
| 702 } | |
| 703 } {1 2 a b 5 6 3 4} | |
| 704 do_test savepoint-10.2.13 { | |
| 705 execsql { ROLLBACK } | |
| 706 execsql { | |
| 707 SELECT * FROM t1; | |
| 708 SELECT * FROM t2; | |
| 709 SELECT * FROM t3; | |
| 710 } | |
| 711 } {1 2 5 6 3 4} | |
| 712 do_test savepoint-10.2.14 { | |
| 713 execsql { PRAGMA lock_status } | |
| 714 } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] | |
| 715 | |
| 716 #------------------------------------------------------------------------- | |
| 717 # The following tests - savepoint-11.* - test the interaction of | |
| 718 # savepoints and creating or dropping tables and indexes in | |
| 719 # auto-vacuum mode. | |
| 720 # | |
| 721 do_test savepoint-11.1 { | |
| 722 db close | |
| 723 file delete -force test.db | |
| 724 sqlite3 db test.db | |
| 725 execsql { | |
| 726 PRAGMA auto_vacuum = full; | |
| 727 CREATE TABLE t1(a, b, UNIQUE(a, b)); | |
| 728 INSERT INTO t1 VALUES(1, randstr(1000,1000)); | |
| 729 INSERT INTO t1 VALUES(2, randstr(1000,1000)); | |
| 730 } | |
| 731 } {} | |
| 732 do_test savepoint-11.2 { | |
| 733 execsql { | |
| 734 SAVEPOINT one; | |
| 735 CREATE TABLE t2(a, b, UNIQUE(a, b)); | |
| 736 SAVEPOINT two; | |
| 737 CREATE TABLE t3(a, b, UNIQUE(a, b)); | |
| 738 } | |
| 739 } {} | |
| 740 integrity_check savepoint-11.3 | |
| 741 do_test savepoint-11.4 { | |
| 742 execsql { ROLLBACK TO two } | |
| 743 } {} | |
| 744 integrity_check savepoint-11.5 | |
| 745 do_test savepoint-11.6 { | |
| 746 execsql { | |
| 747 CREATE TABLE t3(a, b, UNIQUE(a, b)); | |
| 748 ROLLBACK TO one; | |
| 749 } | |
| 750 } {} | |
| 751 integrity_check savepoint-11.7 | |
| 752 do_test savepoint-11.8 { | |
| 753 execsql { ROLLBACK } | |
| 754 file size test.db | |
| 755 } {8192} | |
| 756 | |
| 757 | |
| 758 do_test savepoint-11.9 { | |
| 759 execsql { | |
| 760 DROP TABLE IF EXISTS t1; | |
| 761 DROP TABLE IF EXISTS t2; | |
| 762 DROP TABLE IF EXISTS t3; | |
| 763 } | |
| 764 } {} | |
| 765 do_test savepoint-11.10 { | |
| 766 execsql { | |
| 767 BEGIN; | |
| 768 CREATE TABLE t1(a, b); | |
| 769 CREATE TABLE t2(x, y); | |
| 770 INSERT INTO t2 VALUES(1, 2); | |
| 771 SAVEPOINT one; | |
| 772 INSERT INTO t2 VALUES(3, 4); | |
| 773 SAVEPOINT two; | |
| 774 DROP TABLE t1; | |
| 775 ROLLBACK TO two; | |
| 776 } | |
| 777 execsql {SELECT * FROM t2} | |
| 778 } {1 2 3 4} | |
| 779 do_test savepoint-11.11 { | |
| 780 execsql COMMIT | |
| 781 } {} | |
| 782 do_test savepoint-11.12 { | |
| 783 execsql {SELECT * FROM t2} | |
| 784 } {1 2 3 4} | |
| 785 | |
| 786 #------------------------------------------------------------------------- | |
| 787 # The following tests - savepoint-12.* - test the interaction of | |
| 788 # savepoints and "ON CONFLICT ROLLBACK" clauses. | |
| 789 # | |
| 790 do_test savepoint-12.1 { | |
| 791 execsql { | |
| 792 CREATE TABLE t4(a PRIMARY KEY, b); | |
| 793 INSERT INTO t4 VALUES(1, 'one'); | |
| 794 } | |
| 795 } {} | |
| 796 do_test savepoint-12.2 { | |
| 797 # The final statement of the following SQL hits a constraint when the | |
| 798 # conflict handling mode is "OR ROLLBACK" and there are a couple of | |
| 799 # open savepoints. At one point this would fail to clear the internal | |
| 800 # record of the open savepoints, resulting in an assert() failure | |
| 801 # later on. | |
| 802 # | |
| 803 catchsql { | |
| 804 BEGIN; | |
| 805 INSERT INTO t4 VALUES(2, 'two'); | |
| 806 SAVEPOINT sp1; | |
| 807 INSERT INTO t4 VALUES(3, 'three'); | |
| 808 SAVEPOINT sp2; | |
| 809 INSERT OR ROLLBACK INTO t4 VALUES(1, 'one'); | |
| 810 } | |
| 811 } {1 {column a is not unique}} | |
| 812 do_test savepoint-12.3 { | |
| 813 sqlite3_get_autocommit db | |
| 814 } {1} | |
| 815 do_test savepoint-12.4 { | |
| 816 execsql { SAVEPOINT one } | |
| 817 } {} | |
| 818 | |
| 819 #------------------------------------------------------------------------- | |
| 820 # The following tests - savepoint-13.* - test the interaction of | |
| 821 # savepoints and "journal_mode = off". | |
| 822 # | |
| 823 do_test savepoint-13.1 { | |
| 824 db close | |
| 825 catch {file delete -force test.db} | |
| 826 sqlite3 db test.db | |
| 827 execsql { | |
| 828 BEGIN; | |
| 829 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 830 INSERT INTO t1 VALUES(1, 2); | |
| 831 COMMIT; | |
| 832 PRAGMA journal_mode = off; | |
| 833 } | |
| 834 } {off} | |
| 835 do_test savepoint-13.2 { | |
| 836 execsql { | |
| 837 BEGIN; | |
| 838 INSERT INTO t1 VALUES(3, 4); | |
| 839 INSERT INTO t1 SELECT a+4,b+4 FROM t1; | |
| 840 COMMIT; | |
| 841 } | |
| 842 } {} | |
| 843 do_test savepoint-13.3 { | |
| 844 execsql { | |
| 845 BEGIN; | |
| 846 INSERT INTO t1 VALUES(9, 10); | |
| 847 SAVEPOINT s1; | |
| 848 INSERT INTO t1 VALUES(11, 12); | |
| 849 COMMIT; | |
| 850 } | |
| 851 } {} | |
| 852 do_test savepoint-13.4 { | |
| 853 execsql { | |
| 854 BEGIN; | |
| 855 INSERT INTO t1 VALUES(13, 14); | |
| 856 SAVEPOINT s1; | |
| 857 INSERT INTO t1 VALUES(15, 16); | |
| 858 ROLLBACK TO s1; | |
| 859 ROLLBACK; | |
| 860 SELECT * FROM t1; | |
| 861 } | |
| 862 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} | |
| 863 | |
| 864 finish_test | |
| OLD | NEW |