xref: /sqlite-3.40.0/test/delete2.test (revision 9ffe5d72)
18dcd7cabSdrh# 2003 September 6
28dcd7cabSdrh#
38dcd7cabSdrh# The author disclaims copyright to this source code.  In place of
48dcd7cabSdrh# a legal notice, here is a blessing:
58dcd7cabSdrh#
68dcd7cabSdrh#    May you do good and not evil.
78dcd7cabSdrh#    May you find forgiveness for yourself and forgive others.
88dcd7cabSdrh#    May you share freely, never taking more than you give.
98dcd7cabSdrh#
108dcd7cabSdrh#***********************************************************************
118dcd7cabSdrh# This file implements regression tests for SQLite library.  The
128dcd7cabSdrh# focus of this script is a test to replicate the bug reported by
138dcd7cabSdrh# ticket #842.
148dcd7cabSdrh#
158dcd7cabSdrh# Ticket #842 was a database corruption problem caused by a DELETE that
168dcd7cabSdrh# removed an index entry by not the main table entry.  To recreate the
178dcd7cabSdrh# problem do this:
188dcd7cabSdrh#
198dcd7cabSdrh#   (1) Create a table with an index.  Insert some data into that table.
208dcd7cabSdrh#   (2) Start a query on the table but do not complete the query.
218dcd7cabSdrh#   (3) Try to delete a single entry from the table.
228dcd7cabSdrh#
238dcd7cabSdrh# Step 3 will fail because there is still a read cursor on the table.
248dcd7cabSdrh# But the database is corrupted by the DELETE.  It turns out that the
258dcd7cabSdrh# index entry was deleted first, before the table entry.  And the index
268dcd7cabSdrh# delete worked.  Thus an entry was deleted from the index but not from
278dcd7cabSdrh# the table.
288dcd7cabSdrh#
298dcd7cabSdrh# The solution to the problem was to detect that the table is locked
308dcd7cabSdrh# before the index entry is deleted.
318dcd7cabSdrh#
32*9ffe5d72Sdanielk1977# $Id: delete2.test,v 1.8 2008/07/08 15:59:52 danielk1977 Exp $
338dcd7cabSdrh#
348dcd7cabSdrh
358dcd7cabSdrhset testdir [file dirname $argv0]
368dcd7cabSdrhsource $testdir/tester.tcl
378dcd7cabSdrh
388dcd7cabSdrh# Create a table that has an index.
398dcd7cabSdrh#
408dcd7cabSdrhdo_test delete2-1.1 {
41dddca286Sdrh  set DB [sqlite3_connection_pointer db]
428dcd7cabSdrh  execsql {
438dcd7cabSdrh    CREATE TABLE q(s string, id string, constraint pk_q primary key(id));
448dcd7cabSdrh    BEGIN;
458dcd7cabSdrh    INSERT INTO q(s,id) VALUES('hello','id.1');
468dcd7cabSdrh    INSERT INTO q(s,id) VALUES('goodbye','id.2');
478dcd7cabSdrh    INSERT INTO q(s,id) VALUES('again','id.3');
488dcd7cabSdrh    END;
498dcd7cabSdrh    SELECT * FROM q;
508dcd7cabSdrh  }
518dcd7cabSdrh} {hello id.1 goodbye id.2 again id.3}
528dcd7cabSdrhdo_test delete2-1.2 {
538dcd7cabSdrh  execsql {
548dcd7cabSdrh    SELECT * FROM q WHERE id='id.1';
558dcd7cabSdrh  }
568dcd7cabSdrh} {hello id.1}
5740e016e4Sdrhintegrity_check delete2-1.3
588dcd7cabSdrh
598dcd7cabSdrh# Start a query on the table.  The query should not use the index.
608dcd7cabSdrh# Do not complete the query, thus leaving the table locked.
618dcd7cabSdrh#
628dcd7cabSdrhdo_test delete2-1.4 {
638dcd7cabSdrh  set STMT [sqlite3_prepare $DB {SELECT * FROM q} -1 TAIL]
648dcd7cabSdrh  sqlite3_step $STMT
658dcd7cabSdrh} SQLITE_ROW
6640e016e4Sdrhintegrity_check delete2-1.5
678dcd7cabSdrh
68980b1a74Sdrh# Try to delete a row from the table while a read is in process.
69980b1a74Sdrh# As of 2006-08-16, this is allowed.  (It used to fail with SQLITE_LOCKED.)
708dcd7cabSdrh#
718dcd7cabSdrhdo_test delete2-1.6 {
728dcd7cabSdrh  catchsql {
738dcd7cabSdrh    DELETE FROM q WHERE rowid=1
748dcd7cabSdrh  }
75980b1a74Sdrh} {0 {}}
7640e016e4Sdrhintegrity_check delete2-1.7
778dcd7cabSdrhdo_test delete2-1.8 {
788dcd7cabSdrh  execsql {
798dcd7cabSdrh    SELECT * FROM q;
808dcd7cabSdrh  }
81980b1a74Sdrh} {goodbye id.2 again id.3}
828dcd7cabSdrh
8312b13002Sdanielk1977# Finalize the query, thus clearing the lock on the table.  Then
8412b13002Sdanielk1977# retry the delete.  The delete should work this time.
8512b13002Sdanielk1977#
868dcd7cabSdrhdo_test delete2-1.9 {
878dcd7cabSdrh  sqlite3_finalize $STMT
888dcd7cabSdrh  catchsql {
8912b13002Sdanielk1977    DELETE FROM q WHERE rowid=1
908dcd7cabSdrh  }
918dcd7cabSdrh} {0 {}}
9240e016e4Sdrhintegrity_check delete2-1.10
938dcd7cabSdrhdo_test delete2-1.11 {
948dcd7cabSdrh  execsql {
958dcd7cabSdrh    SELECT * FROM q;
968dcd7cabSdrh  }
9712b13002Sdanielk1977} {goodbye id.2 again id.3}
988dcd7cabSdrh
99*9ffe5d72Sdanielk1977do_test delete2-2.1 {
100*9ffe5d72Sdanielk1977  execsql {
101*9ffe5d72Sdanielk1977    CREATE TABLE t1(a, b);
102*9ffe5d72Sdanielk1977    CREATE TABLE t2(c, d);
103*9ffe5d72Sdanielk1977    INSERT INTO t1 VALUES(1, 2);
104*9ffe5d72Sdanielk1977    INSERT INTO t2 VALUES(3, 4);
105*9ffe5d72Sdanielk1977    INSERT INTO t2 VALUES(5, 6);
106*9ffe5d72Sdanielk1977  }
107*9ffe5d72Sdanielk1977} {}
108*9ffe5d72Sdanielk1977do_test delete2-2.2 {
109*9ffe5d72Sdanielk1977  set res [list]
110*9ffe5d72Sdanielk1977  db eval {
111*9ffe5d72Sdanielk1977    SELECT CASE WHEN c = 5 THEN b ELSE NULL END AS b, c, d FROM t1, t2
112*9ffe5d72Sdanielk1977  } {
113*9ffe5d72Sdanielk1977    db eval {DELETE FROM t1}
114*9ffe5d72Sdanielk1977    lappend res $b $c $d
115*9ffe5d72Sdanielk1977  }
116*9ffe5d72Sdanielk1977  set res
117*9ffe5d72Sdanielk1977} {{} 3 4 {} 5 6}
118*9ffe5d72Sdanielk1977
1198dcd7cabSdrhfinish_test
120