1fd7f0452Sdanielk1977# 2008 December 15 2fd7f0452Sdanielk1977# 3fd7f0452Sdanielk1977# The author disclaims copyright to this source code. In place of 4fd7f0452Sdanielk1977# a legal notice, here is a blessing: 5fd7f0452Sdanielk1977# 6fd7f0452Sdanielk1977# May you do good and not evil. 7fd7f0452Sdanielk1977# May you find forgiveness for yourself and forgive others. 8fd7f0452Sdanielk1977# May you share freely, never taking more than you give. 9fd7f0452Sdanielk1977# 10fd7f0452Sdanielk1977#*********************************************************************** 11fd7f0452Sdanielk1977# 12627a3d6aSdanielk1977# $Id: savepoint.test,v 1.13 2009/07/18 08:30:45 danielk1977 Exp $ 13fd7f0452Sdanielk1977 14fd7f0452Sdanielk1977set testdir [file dirname $argv0] 15fd7f0452Sdanielk1977source $testdir/tester.tcl 16ab7e8d85Sdansource $testdir/lock_common.tcl 17ab7e8d85Sdansource $testdir/malloc_common.tcl 18fd7f0452Sdanielk1977 19*bc2e7fc2Sdanforcedelete test2.db 20*bc2e7fc2Sdan 21fd7f0452Sdanielk1977#---------------------------------------------------------------------- 22fd7f0452Sdanielk1977# The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE 23fd7f0452Sdanielk1977# and ROLLBACK TO comands are correctly parsed, and that the auto-commit 24fd7f0452Sdanielk1977# flag is correctly set and unset as a result. 25fd7f0452Sdanielk1977# 26fd7f0452Sdanielk1977do_test savepoint-1.1 { 2771cb518fSdan wal_set_journal_mode 28fd7f0452Sdanielk1977 execsql { 29fd7f0452Sdanielk1977 SAVEPOINT sp1; 30fd7f0452Sdanielk1977 RELEASE sp1; 31fd7f0452Sdanielk1977 } 32fd7f0452Sdanielk1977} {} 33fd7f0452Sdanielk1977do_test savepoint-1.2 { 34fd7f0452Sdanielk1977 execsql { 35fd7f0452Sdanielk1977 SAVEPOINT sp1; 36fd7f0452Sdanielk1977 ROLLBACK TO sp1; 37fd7f0452Sdanielk1977 } 38fd7f0452Sdanielk1977} {} 39fd7f0452Sdanielk1977do_test savepoint-1.3 { 40fd7f0452Sdanielk1977 execsql { SAVEPOINT sp1 } 41fd7f0452Sdanielk1977 db close 42fd7f0452Sdanielk1977} {} 43fd7f0452Sdanielk1977sqlite3 db test.db 44fd7f0452Sdanielk1977do_test savepoint-1.4.1 { 45fd7f0452Sdanielk1977 execsql { 46fd7f0452Sdanielk1977 SAVEPOINT sp1; 47fd7f0452Sdanielk1977 SAVEPOINT sp2; 48fd7f0452Sdanielk1977 RELEASE sp1; 49fd7f0452Sdanielk1977 } 50fd7f0452Sdanielk1977 sqlite3_get_autocommit db 51fd7f0452Sdanielk1977} {1} 52fd7f0452Sdanielk1977do_test savepoint-1.4.2 { 53fd7f0452Sdanielk1977 execsql { 54fd7f0452Sdanielk1977 SAVEPOINT sp1; 55fd7f0452Sdanielk1977 SAVEPOINT sp2; 56fd7f0452Sdanielk1977 RELEASE sp2; 57fd7f0452Sdanielk1977 } 58fd7f0452Sdanielk1977 sqlite3_get_autocommit db 59fd7f0452Sdanielk1977} {0} 60fd7f0452Sdanielk1977do_test savepoint-1.4.3 { 61fd7f0452Sdanielk1977 execsql { RELEASE sp1 } 62fd7f0452Sdanielk1977 sqlite3_get_autocommit db 63fd7f0452Sdanielk1977} {1} 64fd7f0452Sdanielk1977do_test savepoint-1.4.4 { 65fd7f0452Sdanielk1977 execsql { 66fd7f0452Sdanielk1977 SAVEPOINT sp1; 67fd7f0452Sdanielk1977 SAVEPOINT sp2; 68fd7f0452Sdanielk1977 ROLLBACK TO sp1; 69fd7f0452Sdanielk1977 } 70fd7f0452Sdanielk1977 sqlite3_get_autocommit db 71fd7f0452Sdanielk1977} {0} 72fd7f0452Sdanielk1977do_test savepoint-1.4.5 { 73fd7f0452Sdanielk1977 execsql { RELEASE SAVEPOINT sp1 } 74fd7f0452Sdanielk1977 sqlite3_get_autocommit db 75fd7f0452Sdanielk1977} {1} 76fd7f0452Sdanielk1977do_test savepoint-1.4.6 { 77fd7f0452Sdanielk1977 execsql { 78fd7f0452Sdanielk1977 SAVEPOINT sp1; 79fd7f0452Sdanielk1977 SAVEPOINT sp2; 80fd7f0452Sdanielk1977 SAVEPOINT sp3; 81fd7f0452Sdanielk1977 ROLLBACK TO SAVEPOINT sp3; 82fd7f0452Sdanielk1977 ROLLBACK TRANSACTION TO sp2; 83fd7f0452Sdanielk1977 ROLLBACK TRANSACTION TO SAVEPOINT sp1; 84fd7f0452Sdanielk1977 } 85fd7f0452Sdanielk1977 sqlite3_get_autocommit db 86fd7f0452Sdanielk1977} {0} 87fd7f0452Sdanielk1977do_test savepoint-1.4.7 { 88fd7f0452Sdanielk1977 execsql { RELEASE SAVEPOINT SP1 } 89fd7f0452Sdanielk1977 sqlite3_get_autocommit db 90fd7f0452Sdanielk1977} {1} 91fd7f0452Sdanielk1977do_test savepoint-1.5 { 92fd7f0452Sdanielk1977 execsql { 93fd7f0452Sdanielk1977 SAVEPOINT sp1; 94fd7f0452Sdanielk1977 ROLLBACK TO sp1; 95fd7f0452Sdanielk1977 } 96fd7f0452Sdanielk1977} {} 97fd7f0452Sdanielk1977do_test savepoint-1.6 { 98fd7f0452Sdanielk1977 execsql COMMIT 99fd7f0452Sdanielk1977} {} 10071cb518fSdanwal_check_journal_mode savepoint-1.7 101fd7f0452Sdanielk1977 102fd7f0452Sdanielk1977#------------------------------------------------------------------------ 103fd7f0452Sdanielk1977# These tests - savepoint-2.* - test rollbacks and releases of savepoints 104fd7f0452Sdanielk1977# with a very simple data set. 105fd7f0452Sdanielk1977# 106fd7f0452Sdanielk1977 107fd7f0452Sdanielk1977do_test savepoint-2.1 { 108fd7f0452Sdanielk1977 execsql { 109fd7f0452Sdanielk1977 CREATE TABLE t1(a, b, c); 110fd7f0452Sdanielk1977 BEGIN; 111fd7f0452Sdanielk1977 INSERT INTO t1 VALUES(1, 2, 3); 112fd7f0452Sdanielk1977 SAVEPOINT one; 113fd7f0452Sdanielk1977 UPDATE t1 SET a = 2, b = 3, c = 4; 114fd7f0452Sdanielk1977 } 115fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 116fd7f0452Sdanielk1977} {2 3 4} 117fd7f0452Sdanielk1977do_test savepoint-2.2 { 118fd7f0452Sdanielk1977 execsql { 119fd7f0452Sdanielk1977 ROLLBACK TO one; 120fd7f0452Sdanielk1977 } 121fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 122fd7f0452Sdanielk1977} {1 2 3} 123fd7f0452Sdanielk1977do_test savepoint-2.3 { 124fd7f0452Sdanielk1977 execsql { 125fd7f0452Sdanielk1977 INSERT INTO t1 VALUES(4, 5, 6); 126fd7f0452Sdanielk1977 } 127fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 128fd7f0452Sdanielk1977} {1 2 3 4 5 6} 129fd7f0452Sdanielk1977do_test savepoint-2.4 { 130fd7f0452Sdanielk1977 execsql { 131fd7f0452Sdanielk1977 ROLLBACK TO one; 132fd7f0452Sdanielk1977 } 133fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 134fd7f0452Sdanielk1977} {1 2 3} 135fd7f0452Sdanielk1977 136fd7f0452Sdanielk1977 137fd7f0452Sdanielk1977do_test savepoint-2.5 { 138fd7f0452Sdanielk1977 execsql { 139fd7f0452Sdanielk1977 INSERT INTO t1 VALUES(7, 8, 9); 140fd7f0452Sdanielk1977 SAVEPOINT two; 141fd7f0452Sdanielk1977 INSERT INTO t1 VALUES(10, 11, 12); 142fd7f0452Sdanielk1977 } 143fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 144fd7f0452Sdanielk1977} {1 2 3 7 8 9 10 11 12} 145fd7f0452Sdanielk1977do_test savepoint-2.6 { 146fd7f0452Sdanielk1977 execsql { 147fd7f0452Sdanielk1977 ROLLBACK TO two; 148fd7f0452Sdanielk1977 } 149fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 150fd7f0452Sdanielk1977} {1 2 3 7 8 9} 151fd7f0452Sdanielk1977do_test savepoint-2.7 { 152fd7f0452Sdanielk1977 execsql { 153fd7f0452Sdanielk1977 INSERT INTO t1 VALUES(10, 11, 12); 154fd7f0452Sdanielk1977 } 155fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 156fd7f0452Sdanielk1977} {1 2 3 7 8 9 10 11 12} 157fd7f0452Sdanielk1977do_test savepoint-2.8 { 158fd7f0452Sdanielk1977 execsql { 159fd7f0452Sdanielk1977 ROLLBACK TO one; 160fd7f0452Sdanielk1977 } 161fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 162fd7f0452Sdanielk1977} {1 2 3} 163fd7f0452Sdanielk1977do_test savepoint-2.9 { 164fd7f0452Sdanielk1977 execsql { 165fd7f0452Sdanielk1977 INSERT INTO t1 VALUES('a', 'b', 'c'); 166fd7f0452Sdanielk1977 SAVEPOINT two; 167fd7f0452Sdanielk1977 INSERT INTO t1 VALUES('d', 'e', 'f'); 168fd7f0452Sdanielk1977 } 169fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 170fd7f0452Sdanielk1977} {1 2 3 a b c d e f} 171fd7f0452Sdanielk1977do_test savepoint-2.10 { 172fd7f0452Sdanielk1977 execsql { 173fd7f0452Sdanielk1977 RELEASE two; 174fd7f0452Sdanielk1977 } 175fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 176fd7f0452Sdanielk1977} {1 2 3 a b c d e f} 177fd7f0452Sdanielk1977do_test savepoint-2.11 { 178fd7f0452Sdanielk1977 execsql { 179fd7f0452Sdanielk1977 ROLLBACK; 180fd7f0452Sdanielk1977 } 181fd7f0452Sdanielk1977 execsql { SELECT * FROM t1 } 182fd7f0452Sdanielk1977} {} 18371cb518fSdanwal_check_journal_mode savepoint-2.12 184fd7f0452Sdanielk1977 185fd7f0452Sdanielk1977#------------------------------------------------------------------------ 186fd7f0452Sdanielk1977# This block of tests - savepoint-3.* - test that when a transaction 187fd7f0452Sdanielk1977# savepoint is rolled back, locks are not released from database files. 188fd7f0452Sdanielk1977# And that when a transaction savepoint is released, they are released. 189fd7f0452Sdanielk1977# 19071cb518fSdan# These tests do not work in WAL mode. WAL mode does not take RESERVED 19171cb518fSdan# locks on the database file. 19271cb518fSdan# 19371cb518fSdanif {[wal_is_wal_mode]==0} { 194fd7f0452Sdanielk1977 do_test savepoint-3.1 { 195fd7f0452Sdanielk1977 execsql { SAVEPOINT "transaction" } 196fd7f0452Sdanielk1977 execsql { PRAGMA lock_status } 197fd7f0452Sdanielk1977 } {main unlocked temp closed} 198fd7f0452Sdanielk1977 199fd7f0452Sdanielk1977 do_test savepoint-3.2 { 200fd7f0452Sdanielk1977 execsql { INSERT INTO t1 VALUES(1, 2, 3) } 201fd7f0452Sdanielk1977 execsql { PRAGMA lock_status } 202fd7f0452Sdanielk1977 } {main reserved temp closed} 203fd7f0452Sdanielk1977 204fd7f0452Sdanielk1977 do_test savepoint-3.3 { 205fd7f0452Sdanielk1977 execsql { ROLLBACK TO "transaction" } 206fd7f0452Sdanielk1977 execsql { PRAGMA lock_status } 207fd7f0452Sdanielk1977 } {main reserved temp closed} 208fd7f0452Sdanielk1977 209fd7f0452Sdanielk1977 do_test savepoint-3.4 { 210fd7f0452Sdanielk1977 execsql { INSERT INTO t1 VALUES(1, 2, 3) } 211fd7f0452Sdanielk1977 execsql { PRAGMA lock_status } 212fd7f0452Sdanielk1977 } {main reserved temp closed} 213fd7f0452Sdanielk1977 214fd7f0452Sdanielk1977 do_test savepoint-3.5 { 215fd7f0452Sdanielk1977 execsql { RELEASE "transaction" } 216fd7f0452Sdanielk1977 execsql { PRAGMA lock_status } 217fd7f0452Sdanielk1977 } {main unlocked temp closed} 21871cb518fSdan} 219fd7f0452Sdanielk1977 220fd7f0452Sdanielk1977#------------------------------------------------------------------------ 221fd7f0452Sdanielk1977# Test that savepoints that include schema modifications are handled 222fd7f0452Sdanielk1977# correctly. Test cases savepoint-4.*. 223fd7f0452Sdanielk1977# 224fd7f0452Sdanielk1977do_test savepoint-4.1 { 225fd7f0452Sdanielk1977 execsql { 226fd7f0452Sdanielk1977 CREATE TABLE t2(d, e, f); 227fd7f0452Sdanielk1977 SELECT sql FROM sqlite_master; 228fd7f0452Sdanielk1977 } 229fd7f0452Sdanielk1977} {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}} 230fd7f0452Sdanielk1977do_test savepoint-4.2 { 231fd7f0452Sdanielk1977 execsql { 232fd7f0452Sdanielk1977 BEGIN; 233fd7f0452Sdanielk1977 CREATE TABLE t3(g,h); 234fd7f0452Sdanielk1977 INSERT INTO t3 VALUES('I', 'II'); 235fd7f0452Sdanielk1977 SAVEPOINT one; 236fd7f0452Sdanielk1977 DROP TABLE t3; 237fd7f0452Sdanielk1977 } 238fd7f0452Sdanielk1977} {} 239fd7f0452Sdanielk1977do_test savepoint-4.3 { 240fd7f0452Sdanielk1977 execsql { 241fd7f0452Sdanielk1977 CREATE TABLE t3(g, h, i); 242fd7f0452Sdanielk1977 INSERT INTO t3 VALUES('III', 'IV', 'V'); 243fd7f0452Sdanielk1977 } 244fd7f0452Sdanielk1977 execsql {SELECT * FROM t3} 245fd7f0452Sdanielk1977} {III IV V} 246fd7f0452Sdanielk1977do_test savepoint-4.4 { 247fd7f0452Sdanielk1977 execsql { ROLLBACK TO one; } 248fd7f0452Sdanielk1977 execsql {SELECT * FROM t3} 249fd7f0452Sdanielk1977} {I II} 250fd7f0452Sdanielk1977do_test savepoint-4.5 { 251fd7f0452Sdanielk1977 execsql { 252fd7f0452Sdanielk1977 ROLLBACK; 253fd7f0452Sdanielk1977 SELECT sql FROM sqlite_master; 254fd7f0452Sdanielk1977 } 255fd7f0452Sdanielk1977} {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}} 256fd7f0452Sdanielk1977 257fd7f0452Sdanielk1977do_test savepoint-4.6 { 258fd7f0452Sdanielk1977 execsql { 259fd7f0452Sdanielk1977 BEGIN; 260fd7f0452Sdanielk1977 INSERT INTO t1 VALUES('o', 't', 't'); 261fd7f0452Sdanielk1977 SAVEPOINT sp1; 262fd7f0452Sdanielk1977 CREATE TABLE t3(a, b, c); 263fd7f0452Sdanielk1977 INSERT INTO t3 VALUES('z', 'y', 'x'); 264fd7f0452Sdanielk1977 } 265fd7f0452Sdanielk1977 execsql {SELECT * FROM t3} 266fd7f0452Sdanielk1977} {z y x} 267fd7f0452Sdanielk1977do_test savepoint-4.7 { 268fd7f0452Sdanielk1977 execsql { 269fd7f0452Sdanielk1977 ROLLBACK TO sp1; 270fd7f0452Sdanielk1977 CREATE TABLE t3(a); 271fd7f0452Sdanielk1977 INSERT INTO t3 VALUES('value'); 272fd7f0452Sdanielk1977 } 273fd7f0452Sdanielk1977 execsql {SELECT * FROM t3} 274fd7f0452Sdanielk1977} {value} 275fd7f0452Sdanielk1977do_test savepoint-4.8 { 276fd7f0452Sdanielk1977 execsql COMMIT 277fd7f0452Sdanielk1977} {} 27871cb518fSdanwal_check_journal_mode savepoint-4.9 279fd7f0452Sdanielk1977 28034cf35daSdanielk1977#------------------------------------------------------------------------ 28134cf35daSdanielk1977# Test some logic errors to do with the savepoint feature. 28234cf35daSdanielk1977# 28334cf35daSdanielk1977 284627a3d6aSdanielk1977ifcapable incrblob { 28534cf35daSdanielk1977 do_test savepoint-5.1.1 { 28634cf35daSdanielk1977 execsql { 28734cf35daSdanielk1977 CREATE TABLE blobs(x); 28834cf35daSdanielk1977 INSERT INTO blobs VALUES('a twentyeight character blob'); 28934cf35daSdanielk1977 } 29034cf35daSdanielk1977 set fd [db incrblob blobs x 1] 29134cf35daSdanielk1977 puts -nonewline $fd "hello" 29234cf35daSdanielk1977 catchsql {SAVEPOINT abc} 29334cf35daSdanielk1977 } {1 {cannot open savepoint - SQL statements in progress}} 29434cf35daSdanielk1977 do_test savepoint-5.1.2 { 29534cf35daSdanielk1977 close $fd 29634cf35daSdanielk1977 catchsql {SAVEPOINT abc} 29734cf35daSdanielk1977 } {0 {}} 29834cf35daSdanielk1977 29934cf35daSdanielk1977 do_test savepoint-5.2 { 30034cf35daSdanielk1977 execsql {RELEASE abc} 30134cf35daSdanielk1977 catchsql {RELEASE abc} 30234cf35daSdanielk1977 } {1 {no such savepoint: abc}} 30334cf35daSdanielk1977 30434cf35daSdanielk1977 do_test savepoint-5.3.1 { 30534cf35daSdanielk1977 execsql {SAVEPOINT abc} 30634cf35daSdanielk1977 catchsql {ROLLBACK TO def} 30734cf35daSdanielk1977 } {1 {no such savepoint: def}} 3080f198a74Sdrh do_test savepoint-5.3.2.1 { 30934cf35daSdanielk1977 execsql {SAVEPOINT def} 31034cf35daSdanielk1977 set fd [db incrblob -readonly blobs x 1] 3110f198a74Sdrh set rc [catch {seek $fd 0;read $fd} res] 3120f198a74Sdrh lappend rc $res 3130f198a74Sdrh } {0 {hellontyeight character blob}} 3140f198a74Sdrh do_test savepoint-5.3.2.2 { 31534cf35daSdanielk1977 catchsql {ROLLBACK TO def} 3160f198a74Sdrh } {0 {}} 3170f198a74Sdrh do_test savepoint-5.3.2.3 { 3180f198a74Sdrh set rc [catch {seek $fd 0; read $fd} res] 3190f198a74Sdrh set rc 32047b7fc78Sdrh } {0} 32134cf35daSdanielk1977 do_test savepoint-5.3.3 { 32234cf35daSdanielk1977 catchsql {RELEASE def} 32334cf35daSdanielk1977 } {0 {}} 32434cf35daSdanielk1977 do_test savepoint-5.3.4 { 32534cf35daSdanielk1977 close $fd 32634cf35daSdanielk1977 execsql {savepoint def} 32734cf35daSdanielk1977 set fd [db incrblob blobs x 1] 32834cf35daSdanielk1977 catchsql {release def} 32934cf35daSdanielk1977 } {1 {cannot release savepoint - SQL statements in progress}} 33034cf35daSdanielk1977 do_test savepoint-5.3.5 { 33134cf35daSdanielk1977 close $fd 33234cf35daSdanielk1977 execsql {release abc} 33334cf35daSdanielk1977 } {} 33434cf35daSdanielk1977 33571cb518fSdan # Rollback mode: 33671cb518fSdan # 33771cb518fSdan # Open a savepoint transaction and insert a row into the database. Then, 33871cb518fSdan # using a second database handle, open a read-only transaction on the 33971cb518fSdan # database file. Check that the savepoint transaction cannot be committed 34071cb518fSdan # until after the read-only transaction has been closed. 34171cb518fSdan # 34271cb518fSdan # WAL mode: 34371cb518fSdan # 34471cb518fSdan # As above, except that the savepoint transaction can be successfully 34571cb518fSdan # committed before the read-only transaction has been closed. 34671cb518fSdan # 34734cf35daSdanielk1977 do_test savepoint-5.4.1 { 34834cf35daSdanielk1977 execsql { 34934cf35daSdanielk1977 SAVEPOINT main; 35034cf35daSdanielk1977 INSERT INTO blobs VALUES('another blob'); 35134cf35daSdanielk1977 } 35234cf35daSdanielk1977 } {} 35334cf35daSdanielk1977 do_test savepoint-5.4.2 { 35434cf35daSdanielk1977 sqlite3 db2 test.db 35571cb518fSdan execsql { BEGIN ; SELECT count(*) FROM blobs } db2 35671cb518fSdan } {1} 35771cb518fSdan if {[wal_is_wal_mode]} { 35871cb518fSdan do_test savepoint-5.4.3 { catchsql "RELEASE main" } {0 {}} 35971cb518fSdan do_test savepoint-5.4.4 { db2 close } {} 36071cb518fSdan } else { 36171cb518fSdan do_test savepoint-5.4.3 { 36234cf35daSdanielk1977 catchsql { RELEASE main } 36334cf35daSdanielk1977 } {1 {database is locked}} 36471cb518fSdan do_test savepoint-5.4.4 { 36534cf35daSdanielk1977 db2 close 36634cf35daSdanielk1977 catchsql { RELEASE main } 36734cf35daSdanielk1977 } {0 {}} 36871cb518fSdan } 36971cb518fSdan do_test savepoint-5.4.5 { 37034cf35daSdanielk1977 execsql { SELECT x FROM blobs WHERE rowid = 2 } 37134cf35daSdanielk1977 } {{another blob}} 37271cb518fSdan do_test savepoint-5.4.6 { 37371cb518fSdan execsql { SELECT count(*) FROM blobs } 37471cb518fSdan } {2} 375627a3d6aSdanielk1977} 37671cb518fSdanwal_check_journal_mode savepoint-5.5 37734cf35daSdanielk1977 3781f58153aSdanielk1977#------------------------------------------------------------------------- 3791f58153aSdanielk1977# The following tests, savepoint-6.*, test an incr-vacuum inside of a 3801f58153aSdanielk1977# couple of nested savepoints. 3811f58153aSdanielk1977# 3821f58153aSdanielk1977ifcapable {autovacuum && pragma} { 3831f58153aSdanielk1977 db close 384fda06befSmistachkin forcedelete test.db 3851f58153aSdanielk1977 sqlite3 db test.db 3861f58153aSdanielk1977 3871f58153aSdanielk1977 do_test savepoint-6.1 { 38871cb518fSdan execsql { PRAGMA auto_vacuum = incremental } 38971cb518fSdan wal_set_journal_mode 3901f58153aSdanielk1977 execsql { 3911f58153aSdanielk1977 CREATE TABLE t1(a, b, c); 3921f58153aSdanielk1977 CREATE INDEX i1 ON t1(a, b); 3931f58153aSdanielk1977 BEGIN; 3941f58153aSdanielk1977 INSERT INTO t1 VALUES(randstr(10,400),randstr(10,400),randstr(10,400)); 3951f58153aSdanielk1977 } 3961f58153aSdanielk1977 set r "randstr(10,400)" 3971f58153aSdanielk1977 for {set ii 0} {$ii < 10} {incr ii} { 3981f58153aSdanielk1977 execsql "INSERT INTO t1 SELECT $r, $r, $r FROM t1" 3991f58153aSdanielk1977 } 4001f58153aSdanielk1977 execsql { COMMIT } 4011f58153aSdanielk1977 } {} 4021f58153aSdanielk1977 4031f58153aSdanielk1977 integrity_check savepoint-6.2 4041f58153aSdanielk1977 4051f58153aSdanielk1977 do_test savepoint-6.3 { 4061f58153aSdanielk1977 execsql { 4071f58153aSdanielk1977 PRAGMA cache_size = 10; 4081f58153aSdanielk1977 BEGIN; 4091f58153aSdanielk1977 UPDATE t1 SET a = randstr(10,10) WHERE (rowid%4)==0; 4101f58153aSdanielk1977 SAVEPOINT one; 4111f58153aSdanielk1977 DELETE FROM t1 WHERE rowid%2; 4121f58153aSdanielk1977 PRAGMA incr_vacuum; 4131f58153aSdanielk1977 SAVEPOINT two; 4141f58153aSdanielk1977 INSERT INTO t1 SELECT randstr(10,400), randstr(10,400), c FROM t1; 4151f58153aSdanielk1977 DELETE FROM t1 WHERE rowid%2; 4161f58153aSdanielk1977 PRAGMA incr_vacuum; 4171f58153aSdanielk1977 ROLLBACK TO one; 4181f58153aSdanielk1977 COMMIT; 4191f58153aSdanielk1977 } 4201f58153aSdanielk1977 } {} 4211f58153aSdanielk1977 4221f58153aSdanielk1977 integrity_check savepoint-6.4 42371cb518fSdan 42471cb518fSdan wal_check_journal_mode savepoint-6.5 4251f58153aSdanielk1977} 4261f58153aSdanielk1977 4273460d19cSdanielk1977#------------------------------------------------------------------------- 4283460d19cSdanielk1977# The following tests, savepoint-7.*, attempt to break the logic 4293460d19cSdanielk1977# surrounding savepoints by growing and shrinking the database file. 4303460d19cSdanielk1977# 4313460d19cSdanielk1977db close 432fda06befSmistachkinforcedelete test.db 4333460d19cSdanielk1977sqlite3 db test.db 4343460d19cSdanielk1977 4353460d19cSdanielk1977do_test savepoint-7.1 { 43671cb518fSdan execsql { PRAGMA auto_vacuum = incremental } 43771cb518fSdan wal_set_journal_mode 4383460d19cSdanielk1977 execsql { 4393460d19cSdanielk1977 PRAGMA cache_size = 10; 4403460d19cSdanielk1977 BEGIN; 4413460d19cSdanielk1977 CREATE TABLE t1(a PRIMARY KEY, b); 4423460d19cSdanielk1977 INSERT INTO t1(a) VALUES('alligator'); 4433460d19cSdanielk1977 INSERT INTO t1(a) VALUES('angelfish'); 4443460d19cSdanielk1977 INSERT INTO t1(a) VALUES('ant'); 4453460d19cSdanielk1977 INSERT INTO t1(a) VALUES('antelope'); 4463460d19cSdanielk1977 INSERT INTO t1(a) VALUES('ape'); 4473460d19cSdanielk1977 INSERT INTO t1(a) VALUES('baboon'); 4483460d19cSdanielk1977 INSERT INTO t1(a) VALUES('badger'); 4493460d19cSdanielk1977 INSERT INTO t1(a) VALUES('bear'); 4503460d19cSdanielk1977 INSERT INTO t1(a) VALUES('beetle'); 4513460d19cSdanielk1977 INSERT INTO t1(a) VALUES('bird'); 4523460d19cSdanielk1977 INSERT INTO t1(a) VALUES('bison'); 4533460d19cSdanielk1977 UPDATE t1 SET b = randstr(1000,1000); 4543460d19cSdanielk1977 UPDATE t1 SET b = b||randstr(1000,1000); 4553460d19cSdanielk1977 UPDATE t1 SET b = b||randstr(1000,1000); 4563460d19cSdanielk1977 UPDATE t1 SET b = b||randstr(10,1000); 4573460d19cSdanielk1977 COMMIT; 4583460d19cSdanielk1977 } 4593460d19cSdanielk1977 expr ([execsql { PRAGMA page_count }] > 20) 4603460d19cSdanielk1977} {1} 4613460d19cSdanielk1977do_test savepoint-7.2.1 { 4623460d19cSdanielk1977 execsql { 4633460d19cSdanielk1977 BEGIN; 4643460d19cSdanielk1977 SAVEPOINT one; 4653460d19cSdanielk1977 CREATE TABLE t2(a, b); 4663460d19cSdanielk1977 INSERT INTO t2 SELECT a, b FROM t1; 4673460d19cSdanielk1977 ROLLBACK TO one; 4683460d19cSdanielk1977 } 4693460d19cSdanielk1977 execsql { 4703460d19cSdanielk1977 PRAGMA integrity_check; 4713460d19cSdanielk1977 } 4723460d19cSdanielk1977} {ok} 4733460d19cSdanielk1977do_test savepoint-7.2.2 { 4743460d19cSdanielk1977 execsql { 4753460d19cSdanielk1977 COMMIT; 4763460d19cSdanielk1977 PRAGMA integrity_check; 4773460d19cSdanielk1977 } 4783460d19cSdanielk1977} {ok} 4793460d19cSdanielk1977 4803460d19cSdanielk1977do_test savepoint-7.3.1 { 4813460d19cSdanielk1977 execsql { 4823460d19cSdanielk1977 CREATE TABLE t2(a, b); 4833460d19cSdanielk1977 INSERT INTO t2 SELECT a, b FROM t1; 4843460d19cSdanielk1977 } 4853460d19cSdanielk1977} {} 4863460d19cSdanielk1977do_test savepoint-7.3.2 { 4873460d19cSdanielk1977 execsql { 4883460d19cSdanielk1977 BEGIN; 4893460d19cSdanielk1977 SAVEPOINT one; 4903460d19cSdanielk1977 DELETE FROM t2; 4913460d19cSdanielk1977 PRAGMA incremental_vacuum; 4923460d19cSdanielk1977 SAVEPOINT two; 4933460d19cSdanielk1977 INSERT INTO t2 SELECT a, b FROM t1; 4943460d19cSdanielk1977 ROLLBACK TO two; 4953460d19cSdanielk1977 COMMIT; 4963460d19cSdanielk1977 } 4973460d19cSdanielk1977 execsql { PRAGMA integrity_check } 4983460d19cSdanielk1977} {ok} 49971cb518fSdanwal_check_journal_mode savepoint-7.3.3 5003460d19cSdanielk1977 5013460d19cSdanielk1977do_test savepoint-7.4.1 { 5023460d19cSdanielk1977 db close 503fda06befSmistachkin forcedelete test.db 5043460d19cSdanielk1977 sqlite3 db test.db 50571cb518fSdan execsql { PRAGMA auto_vacuum = incremental } 50671cb518fSdan wal_set_journal_mode 5073460d19cSdanielk1977 execsql { 5083460d19cSdanielk1977 CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); 5093460d19cSdanielk1977 INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000)); 5103460d19cSdanielk1977 BEGIN; 5113460d19cSdanielk1977 DELETE FROM t1; 5123460d19cSdanielk1977 SAVEPOINT one; 5133460d19cSdanielk1977 PRAGMA incremental_vacuum; 5143460d19cSdanielk1977 ROLLBACK TO one; 5153460d19cSdanielk1977 COMMIT; 5163460d19cSdanielk1977 } 5173460d19cSdanielk1977 5183460d19cSdanielk1977 execsql { PRAGMA integrity_check } 5193460d19cSdanielk1977} {ok} 5203460d19cSdanielk1977 521f2c31ad8Sdanielk1977do_test savepoint-7.5.1 { 522f2c31ad8Sdanielk1977 execsql { 523f2c31ad8Sdanielk1977 PRAGMA incremental_vacuum; 524f2c31ad8Sdanielk1977 CREATE TABLE t5(x, y); 525f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(1, randstr(1000,1000)); 526f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(2, randstr(1000,1000)); 527f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(3, randstr(1000,1000)); 528f2c31ad8Sdanielk1977 529f2c31ad8Sdanielk1977 BEGIN; 530f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(4, randstr(1000,1000)); 531f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(5, randstr(1000,1000)); 532f2c31ad8Sdanielk1977 DELETE FROM t5 WHERE x=1 OR x=2; 533f2c31ad8Sdanielk1977 SAVEPOINT one; 534f2c31ad8Sdanielk1977 PRAGMA incremental_vacuum; 535f2c31ad8Sdanielk1977 SAVEPOINT two; 536f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(1, randstr(1000,1000)); 537f2c31ad8Sdanielk1977 INSERT INTO t5 VALUES(2, randstr(1000,1000)); 538f2c31ad8Sdanielk1977 ROLLBACK TO two; 539f2c31ad8Sdanielk1977 ROLLBACK TO one; 540f2c31ad8Sdanielk1977 COMMIT; 541f2c31ad8Sdanielk1977 PRAGMA integrity_check; 542f2c31ad8Sdanielk1977 } 543f2c31ad8Sdanielk1977} {ok} 544f2c31ad8Sdanielk1977do_test savepoint-7.5.2 { 545f2c31ad8Sdanielk1977 execsql { 546f2c31ad8Sdanielk1977 DROP TABLE t5; 547f2c31ad8Sdanielk1977 } 548f2c31ad8Sdanielk1977} {} 54971cb518fSdanwal_check_journal_mode savepoint-7.5.3 550f2c31ad8Sdanielk1977 551ab9b703fSdanielk1977# Test oddly named and quoted savepoints. 552ab9b703fSdanielk1977# 553ab9b703fSdanielk1977do_test savepoint-8-1 { 554ab9b703fSdanielk1977 execsql { SAVEPOINT "save1" } 555ab9b703fSdanielk1977 execsql { RELEASE save1 } 556ab9b703fSdanielk1977} {} 557ab9b703fSdanielk1977do_test savepoint-8-2 { 558ab9b703fSdanielk1977 execsql { SAVEPOINT "Including whitespace " } 559ab9b703fSdanielk1977 execsql { RELEASE "including Whitespace " } 560ab9b703fSdanielk1977} {} 561ab9b703fSdanielk1977 562ab9b703fSdanielk1977# Test that the authorization callback works. 563ab9b703fSdanielk1977# 564ab9b703fSdanielk1977ifcapable auth { 565ab9b703fSdanielk1977 proc auth {args} { 56632c6a48bSdrh eval lappend ::authdata [lrange $args 0 4] 567ab9b703fSdanielk1977 return SQLITE_OK 568ab9b703fSdanielk1977 } 569ab9b703fSdanielk1977 db auth auth 570ab9b703fSdanielk1977 571ab9b703fSdanielk1977 do_test savepoint-9.1 { 572ab9b703fSdanielk1977 set ::authdata [list] 573ab9b703fSdanielk1977 execsql { SAVEPOINT sp1 } 574ab9b703fSdanielk1977 set ::authdata 575ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT BEGIN sp1 {} {}} 576ab9b703fSdanielk1977 do_test savepoint-9.2 { 577ab9b703fSdanielk1977 set ::authdata [list] 578ab9b703fSdanielk1977 execsql { ROLLBACK TO sp1 } 579ab9b703fSdanielk1977 set ::authdata 580ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {}} 581ab9b703fSdanielk1977 do_test savepoint-9.3 { 582ab9b703fSdanielk1977 set ::authdata [list] 583ab9b703fSdanielk1977 execsql { RELEASE sp1 } 584ab9b703fSdanielk1977 set ::authdata 585ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT RELEASE sp1 {} {}} 586ab9b703fSdanielk1977 587ab9b703fSdanielk1977 proc auth {args} { 58832c6a48bSdrh eval lappend ::authdata [lrange $args 0 4] 589ab9b703fSdanielk1977 return SQLITE_DENY 590ab9b703fSdanielk1977 } 591ab9b703fSdanielk1977 db auth auth 592ab9b703fSdanielk1977 593ab9b703fSdanielk1977 do_test savepoint-9.4 { 594ab9b703fSdanielk1977 set ::authdata [list] 595ab9b703fSdanielk1977 set res [catchsql { SAVEPOINT sp1 }] 596ab9b703fSdanielk1977 concat $::authdata $res 597ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT BEGIN sp1 {} {} 1 {not authorized}} 598ab9b703fSdanielk1977 do_test savepoint-9.5 { 599ab9b703fSdanielk1977 set ::authdata [list] 600ab9b703fSdanielk1977 set res [catchsql { ROLLBACK TO sp1 }] 601ab9b703fSdanielk1977 concat $::authdata $res 602ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {} 1 {not authorized}} 603ab9b703fSdanielk1977 do_test savepoint-9.6 { 604ab9b703fSdanielk1977 set ::authdata [list] 605ab9b703fSdanielk1977 set res [catchsql { RELEASE sp1 }] 606ab9b703fSdanielk1977 concat $::authdata $res 607ab9b703fSdanielk1977 } {SQLITE_SAVEPOINT RELEASE sp1 {} {} 1 {not authorized}} 6087e445fbfSdanielk1977 6097e445fbfSdanielk1977 catch { db eval ROLLBACK } 6107e445fbfSdanielk1977 db auth "" 611ab9b703fSdanielk1977} 6123460d19cSdanielk1977 6137e445fbfSdanielk1977#------------------------------------------------------------------------- 6147e445fbfSdanielk1977# The following tests - savepoint-10.* - test the interaction of 6157e445fbfSdanielk1977# savepoints and ATTACH statements. 6167e445fbfSdanielk1977# 6177e445fbfSdanielk1977 6187e445fbfSdanielk1977# First make sure it is not possible to attach or detach a database while 6197e445fbfSdanielk1977# a savepoint is open (it is not possible if any transaction is open). 6207e445fbfSdanielk1977# 621cf201488Sdrh# UPDATE 2017-07-26: It is not possible to ATTACH and DETACH within a 622cf201488Sdrh# a transaction. 623cf201488Sdrh# 6247e445fbfSdanielk1977do_test savepoint-10.1.1 { 6257e445fbfSdanielk1977 catchsql { 6267e445fbfSdanielk1977 SAVEPOINT one; 6277e445fbfSdanielk1977 ATTACH 'test2.db' AS aux; 628cf201488Sdrh DETACH aux; 6297e445fbfSdanielk1977 } 630cf201488Sdrh} {0 {}} 6317e445fbfSdanielk1977do_test savepoint-10.1.2 { 6327e445fbfSdanielk1977 execsql { 6337e445fbfSdanielk1977 RELEASE one; 6347e445fbfSdanielk1977 ATTACH 'test2.db' AS aux; 6357e445fbfSdanielk1977 } 6367e445fbfSdanielk1977 catchsql { 6377e445fbfSdanielk1977 SAVEPOINT one; 6387e445fbfSdanielk1977 DETACH aux; 639cf201488Sdrh ATTACH 'test2.db' AS aux; 6407e445fbfSdanielk1977 } 641cf201488Sdrh} {0 {}} 6427e445fbfSdanielk1977do_test savepoint-10.1.3 { 6437e445fbfSdanielk1977 execsql { 6447e445fbfSdanielk1977 RELEASE one; 6457e445fbfSdanielk1977 DETACH aux; 6467e445fbfSdanielk1977 } 6477e445fbfSdanielk1977} {} 6487e445fbfSdanielk1977 649f57cf606Sdrh# The lock state of the TEMP database can vary if SQLITE_TEMP_STORE=3 650f57cf606Sdrh# And the following set of tests is only really interested in the status 651f57cf606Sdrh# of the aux1 and aux2 locks. So record the current lock status of 652f57cf606Sdrh# TEMP for use in the answers. 653f57cf606Sdrhset templockstate [lindex [db eval {PRAGMA lock_status}] 3] 654f57cf606Sdrh 655f57cf606Sdrh 65671cb518fSdanif {[wal_is_wal_mode]==0} { 6577e445fbfSdanielk1977 do_test savepoint-10.2.1 { 658fda06befSmistachkin forcedelete test3.db 659fda06befSmistachkin forcedelete test2.db 6607e445fbfSdanielk1977 execsql { 6617e445fbfSdanielk1977 ATTACH 'test2.db' AS aux1; 6627e445fbfSdanielk1977 ATTACH 'test3.db' AS aux2; 6637e445fbfSdanielk1977 DROP TABLE t1; 6647e445fbfSdanielk1977 CREATE TABLE main.t1(x, y); 6657e445fbfSdanielk1977 CREATE TABLE aux1.t2(x, y); 6667e445fbfSdanielk1977 CREATE TABLE aux2.t3(x, y); 6672f56da3fSdan SELECT name FROM sqlite_master; 6682f56da3fSdan SELECT name FROM aux1.sqlite_master; 6697e445fbfSdanielk1977 SELECT name FROM aux2.sqlite_master; 6707e445fbfSdanielk1977 } 6717e445fbfSdanielk1977 } {t1 t2 t3} 6727e445fbfSdanielk1977 do_test savepoint-10.2.2 { 6737e445fbfSdanielk1977 execsql { PRAGMA lock_status } 674f57cf606Sdrh } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] 6757e445fbfSdanielk1977 6767e445fbfSdanielk1977 do_test savepoint-10.2.3 { 6777e445fbfSdanielk1977 execsql { 6787e445fbfSdanielk1977 SAVEPOINT one; 6797e445fbfSdanielk1977 INSERT INTO t1 VALUES(1, 2); 6807e445fbfSdanielk1977 PRAGMA lock_status; 6817e445fbfSdanielk1977 } 682f57cf606Sdrh } [list main reserved temp $templockstate aux1 unlocked aux2 unlocked] 6837e445fbfSdanielk1977 do_test savepoint-10.2.4 { 6847e445fbfSdanielk1977 execsql { 6857e445fbfSdanielk1977 INSERT INTO t3 VALUES(3, 4); 6867e445fbfSdanielk1977 PRAGMA lock_status; 6877e445fbfSdanielk1977 } 688f57cf606Sdrh } [list main reserved temp $templockstate aux1 unlocked aux2 reserved] 6897e445fbfSdanielk1977 do_test savepoint-10.2.5 { 6907e445fbfSdanielk1977 execsql { 6917e445fbfSdanielk1977 SAVEPOINT two; 6927e445fbfSdanielk1977 INSERT INTO t2 VALUES(5, 6); 6937e445fbfSdanielk1977 PRAGMA lock_status; 6947e445fbfSdanielk1977 } 695f57cf606Sdrh } [list main reserved temp $templockstate aux1 reserved aux2 reserved] 6967e445fbfSdanielk1977 do_test savepoint-10.2.6 { 6977e445fbfSdanielk1977 execsql { SELECT * FROM t2 } 6987e445fbfSdanielk1977 } {5 6} 6997e445fbfSdanielk1977 do_test savepoint-10.2.7 { 7007e445fbfSdanielk1977 execsql { ROLLBACK TO two } 7017e445fbfSdanielk1977 execsql { SELECT * FROM t2 } 7027e445fbfSdanielk1977 } {} 7037e445fbfSdanielk1977 do_test savepoint-10.2.8 { 7047e445fbfSdanielk1977 execsql { PRAGMA lock_status } 705f57cf606Sdrh } [list main reserved temp $templockstate aux1 reserved aux2 reserved] 7067e445fbfSdanielk1977 do_test savepoint-10.2.9 { 7072f56da3fSdan execsql { SELECT 'a', * FROM t1 ; SELECT 'b', * FROM t3 } 7087e445fbfSdanielk1977 } {a 1 2 b 3 4} 7097e445fbfSdanielk1977 do_test savepoint-10.2.9 { 7107e445fbfSdanielk1977 execsql { 7117e445fbfSdanielk1977 INSERT INTO t2 VALUES(5, 6); 7127e445fbfSdanielk1977 RELEASE one; 7137e445fbfSdanielk1977 } 7147e445fbfSdanielk1977 execsql { 7157e445fbfSdanielk1977 SELECT * FROM t1; 7167e445fbfSdanielk1977 SELECT * FROM t2; 7177e445fbfSdanielk1977 SELECT * FROM t3; 7187e445fbfSdanielk1977 } 7197e445fbfSdanielk1977 } {1 2 5 6 3 4} 7207e445fbfSdanielk1977 do_test savepoint-10.2.9 { 7217e445fbfSdanielk1977 execsql { PRAGMA lock_status } 722f57cf606Sdrh } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] 7237e445fbfSdanielk1977 7247e445fbfSdanielk1977 do_test savepoint-10.2.10 { 7257e445fbfSdanielk1977 execsql { 7267e445fbfSdanielk1977 SAVEPOINT one; 7277e445fbfSdanielk1977 INSERT INTO t1 VALUES('a', 'b'); 7287e445fbfSdanielk1977 SAVEPOINT two; 7297e445fbfSdanielk1977 INSERT INTO t2 VALUES('c', 'd'); 7307e445fbfSdanielk1977 SAVEPOINT three; 7317e445fbfSdanielk1977 INSERT INTO t3 VALUES('e', 'f'); 7327e445fbfSdanielk1977 } 7337e445fbfSdanielk1977 execsql { 7347e445fbfSdanielk1977 SELECT * FROM t1; 7357e445fbfSdanielk1977 SELECT * FROM t2; 7367e445fbfSdanielk1977 SELECT * FROM t3; 7377e445fbfSdanielk1977 } 7387e445fbfSdanielk1977 } {1 2 a b 5 6 c d 3 4 e f} 7397e445fbfSdanielk1977 do_test savepoint-10.2.11 { 7407e445fbfSdanielk1977 execsql { ROLLBACK TO two } 7417e445fbfSdanielk1977 execsql { 7427e445fbfSdanielk1977 SELECT * FROM t1; 7437e445fbfSdanielk1977 SELECT * FROM t2; 7447e445fbfSdanielk1977 SELECT * FROM t3; 7457e445fbfSdanielk1977 } 7467e445fbfSdanielk1977 } {1 2 a b 5 6 3 4} 7477e445fbfSdanielk1977 do_test savepoint-10.2.12 { 7487e445fbfSdanielk1977 execsql { 7497e445fbfSdanielk1977 INSERT INTO t3 VALUES('g', 'h'); 7507e445fbfSdanielk1977 ROLLBACK TO two; 7517e445fbfSdanielk1977 } 7527e445fbfSdanielk1977 execsql { 7537e445fbfSdanielk1977 SELECT * FROM t1; 7547e445fbfSdanielk1977 SELECT * FROM t2; 7557e445fbfSdanielk1977 SELECT * FROM t3; 7567e445fbfSdanielk1977 } 7577e445fbfSdanielk1977 } {1 2 a b 5 6 3 4} 7587e445fbfSdanielk1977 do_test savepoint-10.2.13 { 7597e445fbfSdanielk1977 execsql { ROLLBACK } 7607e445fbfSdanielk1977 execsql { 7617e445fbfSdanielk1977 SELECT * FROM t1; 7627e445fbfSdanielk1977 SELECT * FROM t2; 7637e445fbfSdanielk1977 SELECT * FROM t3; 7647e445fbfSdanielk1977 } 7657e445fbfSdanielk1977 } {1 2 5 6 3 4} 7667e445fbfSdanielk1977 do_test savepoint-10.2.14 { 7677e445fbfSdanielk1977 execsql { PRAGMA lock_status } 768f57cf606Sdrh } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked] 76971cb518fSdan} 7707e445fbfSdanielk1977 7717e445fbfSdanielk1977#------------------------------------------------------------------------- 7727e445fbfSdanielk1977# The following tests - savepoint-11.* - test the interaction of 7737e445fbfSdanielk1977# savepoints and creating or dropping tables and indexes in 7747e445fbfSdanielk1977# auto-vacuum mode. 7757e445fbfSdanielk1977# 7767e445fbfSdanielk1977do_test savepoint-11.1 { 7777e445fbfSdanielk1977 db close 778fda06befSmistachkin forcedelete test.db 7797e445fbfSdanielk1977 sqlite3 db test.db 78071cb518fSdan execsql { PRAGMA auto_vacuum = full; } 78171cb518fSdan wal_set_journal_mode 7827e445fbfSdanielk1977 execsql { 7837e445fbfSdanielk1977 CREATE TABLE t1(a, b, UNIQUE(a, b)); 7847e445fbfSdanielk1977 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 7857e445fbfSdanielk1977 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 7867e445fbfSdanielk1977 } 7877e445fbfSdanielk1977} {} 7887e445fbfSdanielk1977do_test savepoint-11.2 { 7897e445fbfSdanielk1977 execsql { 7907e445fbfSdanielk1977 SAVEPOINT one; 7917e445fbfSdanielk1977 CREATE TABLE t2(a, b, UNIQUE(a, b)); 7927e445fbfSdanielk1977 SAVEPOINT two; 7937e445fbfSdanielk1977 CREATE TABLE t3(a, b, UNIQUE(a, b)); 7947e445fbfSdanielk1977 } 7957e445fbfSdanielk1977} {} 7967e445fbfSdanielk1977integrity_check savepoint-11.3 7977e445fbfSdanielk1977do_test savepoint-11.4 { 7987e445fbfSdanielk1977 execsql { ROLLBACK TO two } 7997e445fbfSdanielk1977} {} 8007e445fbfSdanielk1977integrity_check savepoint-11.5 8017e445fbfSdanielk1977do_test savepoint-11.6 { 8027e445fbfSdanielk1977 execsql { 8037e445fbfSdanielk1977 CREATE TABLE t3(a, b, UNIQUE(a, b)); 8047e445fbfSdanielk1977 ROLLBACK TO one; 8057e445fbfSdanielk1977 } 8067e445fbfSdanielk1977} {} 8077e445fbfSdanielk1977integrity_check savepoint-11.7 8081fab7b66Sdanielk1977do_test savepoint-11.8 { 8097e445fbfSdanielk1977 execsql { ROLLBACK } 8105a299f91Sdan execsql { PRAGMA wal_checkpoint } 8117e445fbfSdanielk1977 file size test.db 8127e445fbfSdanielk1977} {8192} 8133460d19cSdanielk1977 8141fab7b66Sdanielk1977do_test savepoint-11.9 { 8151fab7b66Sdanielk1977 execsql { 8161fab7b66Sdanielk1977 DROP TABLE IF EXISTS t1; 8171fab7b66Sdanielk1977 DROP TABLE IF EXISTS t2; 8181fab7b66Sdanielk1977 DROP TABLE IF EXISTS t3; 8191fab7b66Sdanielk1977 } 8201fab7b66Sdanielk1977} {} 8211fab7b66Sdanielk1977do_test savepoint-11.10 { 8221fab7b66Sdanielk1977 execsql { 8231fab7b66Sdanielk1977 BEGIN; 8241fab7b66Sdanielk1977 CREATE TABLE t1(a, b); 8251fab7b66Sdanielk1977 CREATE TABLE t2(x, y); 8261fab7b66Sdanielk1977 INSERT INTO t2 VALUES(1, 2); 8271fab7b66Sdanielk1977 SAVEPOINT one; 8281fab7b66Sdanielk1977 INSERT INTO t2 VALUES(3, 4); 8291fab7b66Sdanielk1977 SAVEPOINT two; 8301fab7b66Sdanielk1977 DROP TABLE t1; 8311fab7b66Sdanielk1977 ROLLBACK TO two; 8321fab7b66Sdanielk1977 } 8331fab7b66Sdanielk1977 execsql {SELECT * FROM t2} 8341fab7b66Sdanielk1977} {1 2 3 4} 8351fab7b66Sdanielk1977do_test savepoint-11.11 { 8361fab7b66Sdanielk1977 execsql COMMIT 8371fab7b66Sdanielk1977} {} 8381fab7b66Sdanielk1977do_test savepoint-11.12 { 8391fab7b66Sdanielk1977 execsql {SELECT * FROM t2} 8401fab7b66Sdanielk1977} {1 2 3 4} 84171cb518fSdanwal_check_journal_mode savepoint-11.13 8421fab7b66Sdanielk1977 843fc158bf9Sdanielk1977#------------------------------------------------------------------------- 844fc158bf9Sdanielk1977# The following tests - savepoint-12.* - test the interaction of 845fc158bf9Sdanielk1977# savepoints and "ON CONFLICT ROLLBACK" clauses. 846fc158bf9Sdanielk1977# 847fc158bf9Sdanielk1977do_test savepoint-12.1 { 848fc158bf9Sdanielk1977 execsql { 849fc158bf9Sdanielk1977 CREATE TABLE t4(a PRIMARY KEY, b); 850fc158bf9Sdanielk1977 INSERT INTO t4 VALUES(1, 'one'); 851fc158bf9Sdanielk1977 } 852fc158bf9Sdanielk1977} {} 853fc158bf9Sdanielk1977do_test savepoint-12.2 { 854fc158bf9Sdanielk1977 # The final statement of the following SQL hits a constraint when the 855fc158bf9Sdanielk1977 # conflict handling mode is "OR ROLLBACK" and there are a couple of 856fc158bf9Sdanielk1977 # open savepoints. At one point this would fail to clear the internal 857fc158bf9Sdanielk1977 # record of the open savepoints, resulting in an assert() failure 858fc158bf9Sdanielk1977 # later on. 859fc158bf9Sdanielk1977 # 860fc158bf9Sdanielk1977 catchsql { 861fc158bf9Sdanielk1977 BEGIN; 862fc158bf9Sdanielk1977 INSERT INTO t4 VALUES(2, 'two'); 863fc158bf9Sdanielk1977 SAVEPOINT sp1; 864fc158bf9Sdanielk1977 INSERT INTO t4 VALUES(3, 'three'); 865fc158bf9Sdanielk1977 SAVEPOINT sp2; 866fc158bf9Sdanielk1977 INSERT OR ROLLBACK INTO t4 VALUES(1, 'one'); 867fc158bf9Sdanielk1977 } 868f9c8ce3cSdrh} {1 {UNIQUE constraint failed: t4.a}} 869fc158bf9Sdanielk1977do_test savepoint-12.3 { 870fc158bf9Sdanielk1977 sqlite3_get_autocommit db 871fc158bf9Sdanielk1977} {1} 872fc158bf9Sdanielk1977do_test savepoint-12.4 { 873fc158bf9Sdanielk1977 execsql { SAVEPOINT one } 874fc158bf9Sdanielk1977} {} 87571cb518fSdanwal_check_journal_mode savepoint-12.5 876fc158bf9Sdanielk1977 877651a52faSdanielk1977#------------------------------------------------------------------------- 878651a52faSdanielk1977# The following tests - savepoint-13.* - test the interaction of 879651a52faSdanielk1977# savepoints and "journal_mode = off". 880651a52faSdanielk1977# 88171cb518fSdanif {[wal_is_wal_mode]==0} { 882651a52faSdanielk1977 do_test savepoint-13.1 { 883651a52faSdanielk1977 db close 884fda06befSmistachkin catch {forcedelete test.db} 885651a52faSdanielk1977 sqlite3 db test.db 886651a52faSdanielk1977 execsql { 887651a52faSdanielk1977 BEGIN; 888651a52faSdanielk1977 CREATE TABLE t1(a PRIMARY KEY, b); 889651a52faSdanielk1977 INSERT INTO t1 VALUES(1, 2); 890651a52faSdanielk1977 COMMIT; 891651a52faSdanielk1977 PRAGMA journal_mode = off; 892651a52faSdanielk1977 } 893651a52faSdanielk1977 } {off} 894651a52faSdanielk1977 do_test savepoint-13.2 { 895651a52faSdanielk1977 execsql { 896651a52faSdanielk1977 BEGIN; 897651a52faSdanielk1977 INSERT INTO t1 VALUES(3, 4); 898651a52faSdanielk1977 INSERT INTO t1 SELECT a+4,b+4 FROM t1; 899651a52faSdanielk1977 COMMIT; 900651a52faSdanielk1977 } 901651a52faSdanielk1977 } {} 902651a52faSdanielk1977 do_test savepoint-13.3 { 903651a52faSdanielk1977 execsql { 904651a52faSdanielk1977 BEGIN; 905651a52faSdanielk1977 INSERT INTO t1 VALUES(9, 10); 906651a52faSdanielk1977 SAVEPOINT s1; 907651a52faSdanielk1977 INSERT INTO t1 VALUES(11, 12); 908651a52faSdanielk1977 COMMIT; 909651a52faSdanielk1977 } 910651a52faSdanielk1977 } {} 911651a52faSdanielk1977 do_test savepoint-13.4 { 912651a52faSdanielk1977 execsql { 913651a52faSdanielk1977 BEGIN; 914651a52faSdanielk1977 INSERT INTO t1 VALUES(13, 14); 915651a52faSdanielk1977 SAVEPOINT s1; 916651a52faSdanielk1977 INSERT INTO t1 VALUES(15, 16); 917651a52faSdanielk1977 ROLLBACK TO s1; 918651a52faSdanielk1977 ROLLBACK; 919651a52faSdanielk1977 SELECT * FROM t1; 920651a52faSdanielk1977 } 921354bfe03Sdan } {1 2 3 4 5 6 7 8 9 10 11 12} 92271cb518fSdan} 923651a52faSdanielk1977 924ab7e8d85Sdandb close 925fda06befSmistachkindelete_file test.db 926ab7e8d85Sdando_multiclient_test tn { 927ab7e8d85Sdan do_test savepoint-14.$tn.1 { 928ab7e8d85Sdan sql1 { 929ab7e8d85Sdan CREATE TABLE foo(x); 930ab7e8d85Sdan INSERT INTO foo VALUES(1); 931ab7e8d85Sdan INSERT INTO foo VALUES(2); 932ab7e8d85Sdan } 933ab7e8d85Sdan sql2 { 934ab7e8d85Sdan BEGIN; 935ab7e8d85Sdan SELECT * FROM foo; 936ab7e8d85Sdan } 937ab7e8d85Sdan } {1 2} 938ab7e8d85Sdan do_test savepoint-14.$tn.2 { 939ab7e8d85Sdan sql1 { 940ab7e8d85Sdan SAVEPOINT one; 941ab7e8d85Sdan INSERT INTO foo VALUES(1); 942ab7e8d85Sdan } 943ab7e8d85Sdan csql1 { RELEASE one } 944ab7e8d85Sdan } {1 {database is locked}} 945ab7e8d85Sdan do_test savepoint-14.$tn.3 { 946ab7e8d85Sdan sql1 { ROLLBACK TO one } 947ab7e8d85Sdan sql2 { COMMIT } 948ab7e8d85Sdan sql1 { RELEASE one } 949ab7e8d85Sdan } {} 950ab7e8d85Sdan 951ab7e8d85Sdan do_test savepoint-14.$tn.4 { 952ab7e8d85Sdan sql2 { 953ab7e8d85Sdan BEGIN; 954ab7e8d85Sdan SELECT * FROM foo; 955ab7e8d85Sdan } 956ab7e8d85Sdan } {1 2} 957ab7e8d85Sdan do_test savepoint-14.$tn.5 { 958ab7e8d85Sdan sql1 { 959ab7e8d85Sdan SAVEPOINT one; 960ab7e8d85Sdan INSERT INTO foo VALUES(1); 961ab7e8d85Sdan } 962ab7e8d85Sdan csql1 { RELEASE one } 963ab7e8d85Sdan } {1 {database is locked}} 964ab7e8d85Sdan do_test savepoint-14.$tn.6 { 965ab7e8d85Sdan sql2 { COMMIT } 966ab7e8d85Sdan sql1 { 967ab7e8d85Sdan ROLLBACK TO one; 968ab7e8d85Sdan INSERT INTO foo VALUES(3); 969ab7e8d85Sdan INSERT INTO foo VALUES(4); 970ab7e8d85Sdan INSERT INTO foo VALUES(5); 971ab7e8d85Sdan RELEASE one; 972ab7e8d85Sdan } 973ab7e8d85Sdan } {} 974ab7e8d85Sdan do_test savepoint-14.$tn.7 { 975ab7e8d85Sdan sql2 { CREATE INDEX fooidx ON foo(x); } 976ab7e8d85Sdan sql3 { PRAGMA integrity_check } 977ab7e8d85Sdan } {ok} 978ab7e8d85Sdan} 979ab7e8d85Sdan 9809f4127d5Sdando_multiclient_test tn { 9819f4127d5Sdan do_test savepoint-15.$tn.1 { 9829f4127d5Sdan sql1 { 9839f4127d5Sdan CREATE TABLE foo(x); 9849f4127d5Sdan INSERT INTO foo VALUES(1); 9859f4127d5Sdan INSERT INTO foo VALUES(2); 9869f4127d5Sdan } 9879f4127d5Sdan sql2 { BEGIN; SELECT * FROM foo; } 9889f4127d5Sdan } {1 2} 9899f4127d5Sdan do_test savepoint-15.$tn.2 { 9909f4127d5Sdan sql1 { 9919f4127d5Sdan PRAGMA locking_mode = EXCLUSIVE; 9929f4127d5Sdan BEGIN; 9939f4127d5Sdan INSERT INTO foo VALUES(3); 9949f4127d5Sdan } 9959f4127d5Sdan csql1 { COMMIT } 9969f4127d5Sdan } {1 {database is locked}} 9979f4127d5Sdan do_test savepoint-15.$tn.3 { 9989f4127d5Sdan sql1 { ROLLBACK } 9999f4127d5Sdan sql2 { COMMIT } 10009f4127d5Sdan sql1 { 10019f4127d5Sdan INSERT INTO foo VALUES(3); 10029f4127d5Sdan PRAGMA locking_mode = NORMAL; 10039f4127d5Sdan INSERT INTO foo VALUES(4); 10049f4127d5Sdan } 10059f4127d5Sdan sql2 { CREATE INDEX fooidx ON foo(x); } 10069f4127d5Sdan sql3 { PRAGMA integrity_check } 10079f4127d5Sdan } {ok} 10089f4127d5Sdan} 10099f4127d5Sdan 10109f4127d5Sdando_multiclient_test tn { 10119f4127d5Sdan do_test savepoint-16.$tn.1 { 10129f4127d5Sdan sql1 { 10139f4127d5Sdan CREATE TABLE foo(x); 10149f4127d5Sdan INSERT INTO foo VALUES(1); 10159f4127d5Sdan INSERT INTO foo VALUES(2); 10169f4127d5Sdan } 10179f4127d5Sdan } {} 10189f4127d5Sdan do_test savepoint-16.$tn.2 { 10199f4127d5Sdan 10209f4127d5Sdan db eval {SELECT * FROM foo} { 10219f4127d5Sdan sql1 { INSERT INTO foo VALUES(3) } 10229f4127d5Sdan sql2 { SELECT * FROM foo } 10239f4127d5Sdan sql1 { INSERT INTO foo VALUES(4) } 10249f4127d5Sdan break 10259f4127d5Sdan } 10269f4127d5Sdan 10279f4127d5Sdan sql2 { CREATE INDEX fooidx ON foo(x); } 10289f4127d5Sdan sql3 { PRAGMA integrity_check } 10299f4127d5Sdan } {ok} 10309f4127d5Sdan do_test savepoint-16.$tn.3 { 10319f4127d5Sdan sql1 { SELECT * FROM foo } 10329f4127d5Sdan } {1 2 3 4} 10339f4127d5Sdan} 10349f4127d5Sdan 1035c311feecSdan#------------------------------------------------------------------------- 1036c311feecSdan# This next block of tests verifies that a problem reported on the mailing 1037c311feecSdan# list has been resolved. At one point the second "CREATE TABLE t6" would 1038c311feecSdan# fail as table t6 still existed in the internal cache of the db schema 1039c311feecSdan# (even though it had been removed from the database by the ROLLBACK 1040c311feecSdan# command). 1041c311feecSdan# 10422969a587Sdansqlite3 db test.db 1043c311feecSdando_execsql_test savepoint-17.1 { 1044c311feecSdan BEGIN; 1045c311feecSdan CREATE TABLE t6(a, b); 1046c311feecSdan INSERT INTO t6 VALUES(1, 2); 1047c311feecSdan SAVEPOINT one; 1048c311feecSdan INSERT INTO t6 VALUES(3, 4); 1049c311feecSdan ROLLBACK TO one; 1050c311feecSdan SELECT * FROM t6; 1051c311feecSdan ROLLBACK; 1052c311feecSdan} {1 2} 1053c311feecSdan 1054c311feecSdando_execsql_test savepoint-17.2 { 1055c311feecSdan CREATE TABLE t6(a, b); 1056c311feecSdan} {} 1057c311feecSdan 1058fd7f0452Sdanielk1977finish_test 1059