xref: /sqlite-3.40.0/test/savepoint.test (revision bc2e7fc2)
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