xref: /sqlite-3.40.0/test/rollback.test (revision 69aedc8d)
191b48aa1Sdrh# 2004 June 30
291b48aa1Sdrh#
391b48aa1Sdrh# The author disclaims copyright to this source code.  In place of
491b48aa1Sdrh# a legal notice, here is a blessing:
591b48aa1Sdrh#
691b48aa1Sdrh#    May you do good and not evil.
791b48aa1Sdrh#    May you find forgiveness for yourself and forgive others.
891b48aa1Sdrh#    May you share freely, never taking more than you give.
991b48aa1Sdrh#
1091b48aa1Sdrh#***********************************************************************
1191b48aa1Sdrh# This file implements regression tests for SQLite library.  The
1291b48aa1Sdrh# focus of this file is verifying that a rollback in one statement
1391b48aa1Sdrh# caused by an ON CONFLICT ROLLBACK clause aborts any other pending
1491b48aa1Sdrh# statements.
1591b48aa1Sdrh#
166f4c73eeSdanielk1977# $Id: rollback.test,v 1.11 2009/06/26 07:12:07 danielk1977 Exp $
1791b48aa1Sdrh
1891b48aa1Sdrhset testdir [file dirname $argv0]
1991b48aa1Sdrhsource $testdir/tester.tcl
2091b48aa1Sdrh
21dddca286Sdrhset DB [sqlite3_connection_pointer db]
2291b48aa1Sdrh
2391b48aa1Sdrhdo_test rollback-1.1 {
2491b48aa1Sdrh  execsql {
2591b48aa1Sdrh    CREATE TABLE t1(a);
2691b48aa1Sdrh    INSERT INTO t1 VALUES(1);
2791b48aa1Sdrh    INSERT INTO t1 VALUES(2);
2891b48aa1Sdrh    INSERT INTO t1 VALUES(3);
2991b48aa1Sdrh    INSERT INTO t1 VALUES(4);
3091b48aa1Sdrh    SELECT * FROM t1;
3191b48aa1Sdrh  }
3291b48aa1Sdrh} {1 2 3 4}
3391b48aa1Sdrh
343bdca9c9Sdanielk1977ifcapable conflict {
3591b48aa1Sdrh  do_test rollback-1.2 {
3691b48aa1Sdrh    execsql {
3791b48aa1Sdrh      CREATE TABLE t3(a unique on conflict rollback);
3891b48aa1Sdrh      INSERT INTO t3 SELECT a FROM t1;
3991b48aa1Sdrh      BEGIN;
4091b48aa1Sdrh      INSERT INTO t1 SELECT * FROM t1;
4191b48aa1Sdrh    }
4291b48aa1Sdrh  } {}
433bdca9c9Sdanielk1977}
4491b48aa1Sdrhdo_test rollback-1.3 {
4591b48aa1Sdrh  set STMT [sqlite3_prepare $DB "SELECT a FROM t1" -1 TAIL]
4691b48aa1Sdrh  sqlite3_step $STMT
4791b48aa1Sdrh} {SQLITE_ROW}
4891b48aa1Sdrh
493bdca9c9Sdanielk1977ifcapable conflict {
5091b48aa1Sdrh  # This causes a ROLLBACK, which deletes the table out from underneath the
5191b48aa1Sdrh  # SELECT statement.
5291b48aa1Sdrh  #
5391b48aa1Sdrh  do_test rollback-1.4 {
5491b48aa1Sdrh    catchsql {
5591b48aa1Sdrh      INSERT INTO t3 SELECT a FROM t1;
5691b48aa1Sdrh    }
57f9c8ce3cSdrh  } {1 {UNIQUE constraint failed: t3.a}}
5891b48aa1Sdrh
5991b48aa1Sdrh  # Try to continue with the SELECT statement
6091b48aa1Sdrh  #
6191b48aa1Sdrh  do_test rollback-1.5 {
6291b48aa1Sdrh    sqlite3_step $STMT
6347b7fc78Sdrh  } {SQLITE_ROW}
6491b48aa1Sdrh
6591b48aa1Sdrh  # Restart the SELECT statement
6691b48aa1Sdrh  #
6747b7fc78Sdrh  do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK}
684152e677Sdanielk1977} else {
694152e677Sdanielk1977  do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK}
704152e677Sdanielk1977}
714152e677Sdanielk1977
7291b48aa1Sdrhdo_test rollback-1.7 {
7391b48aa1Sdrh  sqlite3_step $STMT
7491b48aa1Sdrh} {SQLITE_ROW}
7591b48aa1Sdrhdo_test rollback-1.8 {
7691b48aa1Sdrh  sqlite3_step $STMT
7791b48aa1Sdrh} {SQLITE_ROW}
7891b48aa1Sdrhdo_test rollback-1.9 {
7991b48aa1Sdrh  sqlite3_finalize $STMT
8091b48aa1Sdrh} {SQLITE_OK}
8191b48aa1Sdrh
82b3175389Sdanielk1977if {$tcl_platform(platform) == "unix"
83430e74cdSdan && [permutation] ne "onefile"
84430e74cdSdan && [permutation] ne "inmemory_journal"
854da30f88Sdan && [permutation] ne "atomic-batch-write"
86*69aedc8dSdan && [atomic_batch_write test.db]==0
87b3175389Sdanielk1977} {
88c56774e2Sdanielk1977  do_test rollback-2.1 {
89c56774e2Sdanielk1977    execsql {
90c56774e2Sdanielk1977      BEGIN;
91c56774e2Sdanielk1977      INSERT INTO t3 VALUES('hello world');
92c56774e2Sdanielk1977    }
93fda06befSmistachkin    forcecopy test.db testA.db
94fda06befSmistachkin    forcecopy test.db-journal testA.db-journal
95c56774e2Sdanielk1977    execsql {
96c56774e2Sdanielk1977      COMMIT;
97c56774e2Sdanielk1977    }
98c56774e2Sdanielk1977  } {}
99c56774e2Sdanielk1977
100c56774e2Sdanielk1977  # At this point files testA.db and testA.db-journal are present in the
101c56774e2Sdanielk1977  # file system. This block adds a master-journal file pointer to the
102c56774e2Sdanielk1977  # end of testA.db-journal. The master-journal file does not exist.
103c56774e2Sdanielk1977  #
104c56774e2Sdanielk1977  set mj [file normalize testA.db-mj-123]
105c56774e2Sdanielk1977  binary scan $mj c* a
106c56774e2Sdanielk1977  set cksum 0
107c56774e2Sdanielk1977  foreach i $a { incr cksum $i }
108c56774e2Sdanielk1977  set mj_pgno [expr $sqlite_pending_byte / 1024]
109c56774e2Sdanielk1977  set zAppend [binary format Ia*IIa8 $mj_pgno $mj [string length $mj] $cksum \
110c56774e2Sdanielk1977    "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
111c56774e2Sdanielk1977  ]
112c56774e2Sdanielk1977  set iOffset [expr (([file size testA.db-journal] + 511)/512)*512]
113c56774e2Sdanielk1977  set fd [open testA.db-journal a+]
114c56774e2Sdanielk1977  fconfigure $fd -encoding binary -translation binary
115c56774e2Sdanielk1977  seek $fd $iOffset
116c56774e2Sdanielk1977  puts -nonewline $fd $zAppend
1176f4c73eeSdanielk1977
1186f4c73eeSdanielk1977  # Also, fix the first journal-header in the journal-file. Because the
1196f4c73eeSdanielk1977  # journal file has not yet been synced, the 8-byte magic string at the
1206f4c73eeSdanielk1977  # start of the first journal-header has not been written by SQLite.
1216f4c73eeSdanielk1977  # So write it now.
1226f4c73eeSdanielk1977  seek $fd 0
1236f4c73eeSdanielk1977  puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
124c56774e2Sdanielk1977  close $fd
125c56774e2Sdanielk1977
126c56774e2Sdanielk1977  # Open a handle on testA.db and use it to query the database. At one
127c56774e2Sdanielk1977  # point the first query would attempt a hot rollback, attempt to open
128c56774e2Sdanielk1977  # the master-journal file and return SQLITE_CANTOPEN when it could not
129c56774e2Sdanielk1977  # be opened. This is incorrect, it should simply delete the journal
130c56774e2Sdanielk1977  # file and proceed with the query.
131c56774e2Sdanielk1977  #
132c56774e2Sdanielk1977  do_test rollback-2.2 {
133c56774e2Sdanielk1977    sqlite3 db2 testA.db
134c56774e2Sdanielk1977    execsql {
135c56774e2Sdanielk1977      SELECT distinct tbl_name FROM sqlite_master;
136c56774e2Sdanielk1977    } db2
137c56774e2Sdanielk1977  } {t1 t3}
138430e74cdSdan  if {[lsearch {exclusive persistent_journal no_journal} [permutation]]<0} {
139c56774e2Sdanielk1977    do_test rollback-2.3 {
140c56774e2Sdanielk1977      file exists testA.db-journal
141c56774e2Sdanielk1977    } 0
14215542621Sdrh  }
143c56774e2Sdanielk1977  do_test rollback-2.4 {
144c56774e2Sdanielk1977    execsql {
145c56774e2Sdanielk1977      SELECT distinct tbl_name FROM sqlite_master;
146c56774e2Sdanielk1977    } db2
147c56774e2Sdanielk1977  } {t1 t3}
148c56774e2Sdanielk1977
149c56774e2Sdanielk1977  db2 close
150c56774e2Sdanielk1977}
151c56774e2Sdanielk1977
15291b48aa1Sdrhfinish_test
153