rollback.test 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. # 2004 June 30
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. # This file implements regression tests for SQLite library. The
  12. # focus of this file is verifying that a rollback in one statement
  13. # caused by an ON CONFLICT ROLLBACK clause aborts any other pending
  14. # statements.
  15. #
  16. # $Id: rollback.test,v 1.11 2009/06/26 07:12:07 danielk1977 Exp $
  17. set testdir [file dirname $argv0]
  18. source $testdir/tester.tcl
  19. set DB [sqlite3_connection_pointer db]
  20. do_test rollback-1.1 {
  21. execsql {
  22. CREATE TABLE t1(a);
  23. INSERT INTO t1 VALUES(1);
  24. INSERT INTO t1 VALUES(2);
  25. INSERT INTO t1 VALUES(3);
  26. INSERT INTO t1 VALUES(4);
  27. SELECT * FROM t1;
  28. }
  29. } {1 2 3 4}
  30. ifcapable conflict {
  31. do_test rollback-1.2 {
  32. execsql {
  33. CREATE TABLE t3(a unique on conflict rollback);
  34. INSERT INTO t3 SELECT a FROM t1;
  35. BEGIN;
  36. INSERT INTO t1 SELECT * FROM t1;
  37. }
  38. } {}
  39. }
  40. do_test rollback-1.3 {
  41. set STMT [sqlite3_prepare $DB "SELECT a FROM t1" -1 TAIL]
  42. sqlite3_step $STMT
  43. } {SQLITE_ROW}
  44. ifcapable conflict {
  45. # This causes a ROLLBACK, which deletes the table out from underneath the
  46. # SELECT statement.
  47. #
  48. do_test rollback-1.4 {
  49. catchsql {
  50. INSERT INTO t3 SELECT a FROM t1;
  51. }
  52. } {1 {column a is not unique}}
  53. # Try to continue with the SELECT statement
  54. #
  55. do_test rollback-1.5 {
  56. sqlite3_step $STMT
  57. } {SQLITE_ERROR}
  58. # Restart the SELECT statement
  59. #
  60. do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_ABORT}
  61. } else {
  62. do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK}
  63. }
  64. do_test rollback-1.7 {
  65. sqlite3_step $STMT
  66. } {SQLITE_ROW}
  67. do_test rollback-1.8 {
  68. sqlite3_step $STMT
  69. } {SQLITE_ROW}
  70. do_test rollback-1.9 {
  71. sqlite3_finalize $STMT
  72. } {SQLITE_OK}
  73. if {$tcl_platform(platform) == "unix"
  74. && [permutation] ne "onefile"
  75. && [permutation] ne "inmemory_journal"
  76. } {
  77. do_test rollback-2.1 {
  78. execsql {
  79. BEGIN;
  80. INSERT INTO t3 VALUES('hello world');
  81. }
  82. forcecopy test.db testA.db
  83. forcecopy test.db-journal testA.db-journal
  84. execsql {
  85. COMMIT;
  86. }
  87. } {}
  88. # At this point files testA.db and testA.db-journal are present in the
  89. # file system. This block adds a master-journal file pointer to the
  90. # end of testA.db-journal. The master-journal file does not exist.
  91. #
  92. set mj [file normalize testA.db-mj-123]
  93. binary scan $mj c* a
  94. set cksum 0
  95. foreach i $a { incr cksum $i }
  96. set mj_pgno [expr $sqlite_pending_byte / 1024]
  97. set zAppend [binary format Ia*IIa8 $mj_pgno $mj [string length $mj] $cksum \
  98. "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  99. ]
  100. set iOffset [expr (([file size testA.db-journal] + 511)/512)*512]
  101. set fd [open testA.db-journal a+]
  102. fconfigure $fd -encoding binary -translation binary
  103. seek $fd $iOffset
  104. puts -nonewline $fd $zAppend
  105. # Also, fix the first journal-header in the journal-file. Because the
  106. # journal file has not yet been synced, the 8-byte magic string at the
  107. # start of the first journal-header has not been written by SQLite.
  108. # So write it now.
  109. seek $fd 0
  110. puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  111. close $fd
  112. # Open a handle on testA.db and use it to query the database. At one
  113. # point the first query would attempt a hot rollback, attempt to open
  114. # the master-journal file and return SQLITE_CANTOPEN when it could not
  115. # be opened. This is incorrect, it should simply delete the journal
  116. # file and proceed with the query.
  117. #
  118. do_test rollback-2.2 {
  119. sqlite3 db2 testA.db
  120. execsql {
  121. SELECT distinct tbl_name FROM sqlite_master;
  122. } db2
  123. } {t1 t3}
  124. if {[lsearch {exclusive persistent_journal no_journal} [permutation]]<0} {
  125. do_test rollback-2.3 {
  126. file exists testA.db-journal
  127. } 0
  128. }
  129. do_test rollback-2.4 {
  130. execsql {
  131. SELECT distinct tbl_name FROM sqlite_master;
  132. } db2
  133. } {t1 t3}
  134. db2 close
  135. }
  136. finish_test