delete2.test 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # 2003 September 6
  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 script is a test to replicate the bug reported by
  13. # ticket #842.
  14. #
  15. # Ticket #842 was a database corruption problem caused by a DELETE that
  16. # removed an index entry by not the main table entry. To recreate the
  17. # problem do this:
  18. #
  19. # (1) Create a table with an index. Insert some data into that table.
  20. # (2) Start a query on the table but do not complete the query.
  21. # (3) Try to delete a single entry from the table.
  22. #
  23. # Step 3 will fail because there is still a read cursor on the table.
  24. # But the database is corrupted by the DELETE. It turns out that the
  25. # index entry was deleted first, before the table entry. And the index
  26. # delete worked. Thus an entry was deleted from the index but not from
  27. # the table.
  28. #
  29. # The solution to the problem was to detect that the table is locked
  30. # before the index entry is deleted.
  31. #
  32. # $Id: delete2.test,v 1.8 2008/07/08 15:59:52 danielk1977 Exp $
  33. #
  34. set testdir [file dirname $argv0]
  35. source $testdir/tester.tcl
  36. # Create a table that has an index.
  37. #
  38. do_test delete2-1.1 {
  39. set DB [sqlite3_connection_pointer db]
  40. execsql {
  41. CREATE TABLE q(s string, id string, constraint pk_q primary key(id));
  42. BEGIN;
  43. INSERT INTO q(s,id) VALUES('hello','id.1');
  44. INSERT INTO q(s,id) VALUES('goodbye','id.2');
  45. INSERT INTO q(s,id) VALUES('again','id.3');
  46. END;
  47. SELECT * FROM q;
  48. }
  49. } {hello id.1 goodbye id.2 again id.3}
  50. do_test delete2-1.2 {
  51. execsql {
  52. SELECT * FROM q WHERE id='id.1';
  53. }
  54. } {hello id.1}
  55. integrity_check delete2-1.3
  56. # Start a query on the table. The query should not use the index.
  57. # Do not complete the query, thus leaving the table locked.
  58. #
  59. do_test delete2-1.4 {
  60. set STMT [sqlite3_prepare $DB {SELECT * FROM q} -1 TAIL]
  61. sqlite3_step $STMT
  62. } SQLITE_ROW
  63. integrity_check delete2-1.5
  64. # Try to delete a row from the table while a read is in process.
  65. # As of 2006-08-16, this is allowed. (It used to fail with SQLITE_LOCKED.)
  66. #
  67. do_test delete2-1.6 {
  68. catchsql {
  69. DELETE FROM q WHERE rowid=1
  70. }
  71. } {0 {}}
  72. integrity_check delete2-1.7
  73. do_test delete2-1.8 {
  74. execsql {
  75. SELECT * FROM q;
  76. }
  77. } {goodbye id.2 again id.3}
  78. # Finalize the query, thus clearing the lock on the table. Then
  79. # retry the delete. The delete should work this time.
  80. #
  81. do_test delete2-1.9 {
  82. sqlite3_finalize $STMT
  83. catchsql {
  84. DELETE FROM q WHERE rowid=1
  85. }
  86. } {0 {}}
  87. integrity_check delete2-1.10
  88. do_test delete2-1.11 {
  89. execsql {
  90. SELECT * FROM q;
  91. }
  92. } {goodbye id.2 again id.3}
  93. do_test delete2-2.1 {
  94. execsql {
  95. CREATE TABLE t1(a, b);
  96. CREATE TABLE t2(c, d);
  97. INSERT INTO t1 VALUES(1, 2);
  98. INSERT INTO t2 VALUES(3, 4);
  99. INSERT INTO t2 VALUES(5, 6);
  100. }
  101. } {}
  102. do_test delete2-2.2 {
  103. set res [list]
  104. db eval {
  105. SELECT CASE WHEN c = 5 THEN b ELSE NULL END AS b, c, d FROM t1, t2
  106. } {
  107. db eval {DELETE FROM t1}
  108. lappend res $b $c $d
  109. }
  110. set res
  111. } {{} 3 4 {} 5 6}
  112. finish_test