572a21c8e9
FossilOrigin-Name: 069679162d8d50e9731831e658aa58f280dbb3e7
230 lines
5.4 KiB
Plaintext
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
|
|
|