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