Files
sqlite/test/unlocked2.test
T

230 lines
5.4 KiB
Plaintext

# 2015 July 26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix unlocked2
do_multiclient_test tn {
do_test 1.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x);
CREATE TABLE t2(y);
}
} {wal}
do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
# Test that an UNLOCKED transaction that allocates/frees no pages does
# not conflict with a transaction that does allocate pages.
do_test 1.$tn.2 {
sql1 {
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(4);
}
sql2 {
INSERT INTO t2 VALUES(randomblob(1500));
}
sql1 {
COMMIT;
}
} {}
do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
# But that an UNLOCKED transaction does conflict with a transaction
# that modifies the db schema.
do_test 1.$tn.3 {
sql1 {
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(5);
}
sql2 {
CREATE TABLE t3(z);
}
list [catch { sql1 COMMIT } msg] $msg
} {1 {database is locked}}
do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
# Test that an UNLOCKED transaction that allocates at least one page
# does not conflict with a transaction that allocates no pages.
do_test 1.$tn.4 {
sql1 {
ROLLBACK;
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(randomblob(1500));
}
sql2 {
INSERT INTO t2 VALUES(8);
}
breakpoint
sql1 {
COMMIT;
}
} {}
do_test 1.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
}
do_multiclient_test tn {
do_test 2.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x UNIQUE);
CREATE TABLE t2(y UNIQUE);
}
} {wal}
do_test 2.$tn.2 {
sql1 {
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(randomblob(1500));
}
sql2 {
INSERT INTO t2 VALUES(randomblob(1500));
}
sql1 COMMIT
} {}
do_test 2.$tn.3 { sql3 { PRAGMA integrity_check } } {ok}
do_test 2.$tn.4 {
sql1 {
BEGIN UNLOCKED;
DELETE FROM t1;
}
sql2 {
DELETE FROM t2;
}
sql1 COMMIT
} {}
do_test 2.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
do_test 2.$tn.6 {
sql1 {
INSERT INTO t1 VALUES(randomblob(1500));
INSERT INTO t1 VALUES(randomblob(1500));
INSERT INTO t2 VALUES(randomblob(1500));
DELETE FROM t1 WHERE rowid=1;
}
sql1 {
BEGIN UNLOCKED;
DELETE FROM t1 WHERE rowid=2;
}
sql2 {
DELETE FROM t2;
}
sql1 COMMIT
} {}
do_test 2.$tn.7 { sql3 { PRAGMA integrity_check } } {ok}
}
#-------------------------------------------------------------------------
# When an UNLOCKED transaction is opened on a database, the nFree and
# iTrunk header fields of the cached version of page 1 are both set
# to 0. This allows an UNLOCKED transaction to use its own private
# free-page-list, which is merged with the main database free-list when
# the transaction is committed.
#
# The following tests check that nFree/iTrunk are correctly restored if
# an UNLOCKED transaction is rolled back, and that savepoint rollbacks
# that occur within UNLOCKED transactions do not incorrectly restore
# these fields to their on-disk values.
#
reset_db
do_execsql_test 3.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
DELETE FROM t1;
} {wal}
do_execsql_test 3.1 {
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(1, 2);
ROLLBACK;
}
do_execsql_test 3.2 { PRAGMA integrity_check } {ok}
do_execsql_test 3.3 { PRAGMA freelist_count } {2}
do_execsql_test 3.4.1 {
BEGIN UNLOCKED;
PRAGMA freelist_count;
} {2}
do_execsql_test 3.4.2 {
SAVEPOINT xyz;
INSERT INTO t1 VALUES(randomblob(1500), NULL);
PRAGMA freelist_count;
} {0}
do_execsql_test 3.4.3 {
ROLLBACK TO xyz;
} {}
do_execsql_test 3.4.4 { PRAGMA freelist_count } {0}
do_execsql_test 3.4.5 { COMMIT; PRAGMA freelist_count } {2}
do_execsql_test 3.4.6 { PRAGMA integrity_check } {ok}
do_execsql_test 3.5.1 {
BEGIN UNLOCKED;
UPDATE t1 SET x=randomblob(10) WHERE y=555;
PRAGMA freelist_count;
} {0}
do_execsql_test 3.5.2 {
ROLLBACK;
PRAGMA freelist_count;
} {2}
do_execsql_test 3.5.3 { PRAGMA integrity_check } {ok}
#-------------------------------------------------------------------------
# Test that nothing goes wrong if an UNLOCKED transaction allocates a
# page at the end of the file, frees it within the same transaction, and
# then has to move the same page to avoid a conflict on COMMIT.
#
do_multiclient_test tn {
do_test 4.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(x);
CREATE TABLE t2(x);
}
} {wal}
do_test 4.$tn.2 {
sql1 {
BEGIN UNLOCKED;
INSERT INTO t1 VALUES(randomblob(1500));
INSERT INTO t1 VALUES(randomblob(1500));
DELETE FROM t1 WHERE rowid = 1;
}
sql2 {
INSERT INTO t2 VALUES(randomblob(1500));
INSERT INTO t2 VALUES(randomblob(1500));
INSERT INTO t2 VALUES(randomblob(1500));
INSERT INTO t2 VALUES(randomblob(1500));
DELETE FROM t2 WHERE rowid IN (1, 2);
}
sql1 COMMIT
} {}
}
finish_test