mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add further tests for the code on this branch. Fix a problem in OOM handling.
FossilOrigin-Name: 195f3340ee4d870420e4f58d44300bab5436b920
This commit is contained in:
@ -62,5 +62,116 @@ do_test 1.3 {
|
|||||||
execsql { SELECT * FROM t1 }
|
execsql { SELECT * FROM t1 }
|
||||||
} {2 two 3 three 1 one 11 eleven 12 five}
|
} {2 two 3 three 1 one 11 eleven 12 five}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
db2 close
|
||||||
|
forcedelete test.db2
|
||||||
|
sqlite3 db2 test.db2
|
||||||
|
|
||||||
|
do_test 2.1 {
|
||||||
|
do_common_sql {
|
||||||
|
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE);
|
||||||
|
INSERT INTO t1 VALUES(1, 1, 1);
|
||||||
|
INSERT INTO t1 VALUES(2, 2, 2);
|
||||||
|
INSERT INTO t1 VALUES(3, 3, 3);
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
do_test 2.2.1 {
|
||||||
|
# It is not possible to apply the changeset generated by the following
|
||||||
|
# SQL, as none of the three updated rows may be updated as part of the
|
||||||
|
# first pass.
|
||||||
|
do_then_apply_sql {
|
||||||
|
UPDATE t1 SET b=0 WHERE a=1;
|
||||||
|
UPDATE t1 SET b=1 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=3;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=1;
|
||||||
|
}
|
||||||
|
db2 eval { SELECT a, b FROM t1 }
|
||||||
|
} {1 1 2 2 3 3}
|
||||||
|
do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
db2 close
|
||||||
|
forcedelete test.db2
|
||||||
|
sqlite3 db2 test.db2
|
||||||
|
|
||||||
|
do_test 3.1 {
|
||||||
|
do_common_sql {
|
||||||
|
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE);
|
||||||
|
INSERT INTO t1 VALUES(1, 1, 1);
|
||||||
|
INSERT INTO t1 VALUES(2, 2, 2);
|
||||||
|
INSERT INTO t1 VALUES(3, 3, 3);
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
do_test 3.3 {
|
||||||
|
do_then_apply_sql {
|
||||||
|
UPDATE t1 SET b=4 WHERE a=3;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=1;
|
||||||
|
}
|
||||||
|
compare_db db db2
|
||||||
|
} {}
|
||||||
|
|
||||||
|
do_test 3.4 {
|
||||||
|
do_then_apply_sql {
|
||||||
|
UPDATE t1 SET b=1 WHERE a=1;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=3;
|
||||||
|
}
|
||||||
|
compare_db db db2
|
||||||
|
} {}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
db2 close
|
||||||
|
forcedelete test.db2
|
||||||
|
sqlite3 db2 test.db2
|
||||||
|
|
||||||
|
do_test 4.1 {
|
||||||
|
do_common_sql {
|
||||||
|
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
|
||||||
|
INSERT INTO t1 VALUES(1, 1);
|
||||||
|
INSERT INTO t1 VALUES(2, 2);
|
||||||
|
INSERT INTO t1 VALUES(3, 3);
|
||||||
|
|
||||||
|
CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
|
||||||
|
INSERT INTO t2 VALUES(1, 1);
|
||||||
|
INSERT INTO t2 VALUES(2, 2);
|
||||||
|
INSERT INTO t2 VALUES(3, 3);
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
do_test 4.2 {
|
||||||
|
do_then_apply_sql {
|
||||||
|
UPDATE t1 SET b=4 WHERE a=3;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=1;
|
||||||
|
|
||||||
|
UPDATE t2 SET b=0 WHERE a=1;
|
||||||
|
UPDATE t2 SET b=1 WHERE a=2;
|
||||||
|
UPDATE t2 SET b=2 WHERE a=3;
|
||||||
|
}
|
||||||
|
compare_db db db2
|
||||||
|
} {}
|
||||||
|
|
||||||
|
do_test 4.3 {
|
||||||
|
do_then_apply_sql {
|
||||||
|
UPDATE t1 SET b=1 WHERE a=1;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=3;
|
||||||
|
|
||||||
|
UPDATE t2 SET b=3 WHERE a=3;
|
||||||
|
UPDATE t2 SET b=2 WHERE a=2;
|
||||||
|
UPDATE t2 SET b=1 WHERE a=1;
|
||||||
|
}
|
||||||
|
compare_db db db2
|
||||||
|
} {}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
75
ext/session/sessionfault2.test
Normal file
75
ext/session/sessionfault2.test
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# 2016 March 31
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
# The focus of this file is testing the session module.
|
||||||
|
#
|
||||||
|
|
||||||
|
if {![info exists testdir]} {
|
||||||
|
set testdir [file join [file dirname [info script]] .. .. test]
|
||||||
|
}
|
||||||
|
source [file join [file dirname [info script]] session_common.tcl]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix sessionfault2
|
||||||
|
|
||||||
|
do_execsql_test 1.0.0 {
|
||||||
|
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
|
||||||
|
INSERT INTO t1 VALUES(1, 1);
|
||||||
|
INSERT INTO t1 VALUES(2, 2);
|
||||||
|
INSERT INTO t1 VALUES(3, 3);
|
||||||
|
|
||||||
|
CREATE TABLE t2(a PRIMARY KEY, b UNIQUE);
|
||||||
|
INSERT INTO t2 VALUES(1, 1);
|
||||||
|
INSERT INTO t2 VALUES(2, 2);
|
||||||
|
INSERT INTO t2 VALUES(3, 3);
|
||||||
|
}
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
do_test 1.0.1 {
|
||||||
|
set ::C [changeset_from_sql {
|
||||||
|
UPDATE t1 SET b=4 WHERE a=3;
|
||||||
|
UPDATE t1 SET b=3 WHERE a=2;
|
||||||
|
UPDATE t1 SET b=2 WHERE a=1;
|
||||||
|
UPDATE t2 SET b=0 WHERE a=1;
|
||||||
|
UPDATE t2 SET b=1 WHERE a=2;
|
||||||
|
UPDATE t2 SET b=2 WHERE a=3;
|
||||||
|
}]
|
||||||
|
set {} {}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
proc xConflict args { return "OMIT" }
|
||||||
|
|
||||||
|
do_faultsim_test 1 -faults oom-p* -prep {
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
sqlite3changeset_apply db $::C xConflict
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||||
|
faultsim_integrity_check
|
||||||
|
|
||||||
|
catch { db eval ROLLBACK }
|
||||||
|
set res [db eval {
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
}]
|
||||||
|
|
||||||
|
if {$testrc==0} {
|
||||||
|
if {$res != "1 2 2 3 3 4 1 0 2 1 3 2"} { error "data error" }
|
||||||
|
} else {
|
||||||
|
if {
|
||||||
|
$res != "1 2 2 3 3 4 1 0 2 1 3 2"
|
||||||
|
&& $res != "1 1 2 2 3 3 1 1 2 2 3 3"
|
||||||
|
} { error "data error!! $res" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
@ -3852,6 +3852,16 @@ static int sessionApplyOneOp(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Attempt to apply the change that the iterator passed as the first argument
|
||||||
|
** currently points to to the database. If a conflict is encountered, invoke
|
||||||
|
** the conflict handler callback.
|
||||||
|
**
|
||||||
|
** The difference between this function and sessionApplyOne() is that this
|
||||||
|
** function handles the case where the conflict-handler is invoked and
|
||||||
|
** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be
|
||||||
|
** retried in some manner.
|
||||||
|
*/
|
||||||
static int sessionApplyOneWithRetry(
|
static int sessionApplyOneWithRetry(
|
||||||
sqlite3 *db, /* Apply change to "main" db of this handle */
|
sqlite3 *db, /* Apply change to "main" db of this handle */
|
||||||
sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */
|
sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */
|
||||||
@ -3864,12 +3874,26 @@ static int sessionApplyOneWithRetry(
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry);
|
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry);
|
||||||
|
assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) );
|
||||||
|
|
||||||
if( rc==SQLITE_OK && bRetry ){
|
/* If the bRetry flag is set, the change has not been applied due to an
|
||||||
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, 0);
|
** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and
|
||||||
|
** a row with the correct PK is present in the db, but one or more other
|
||||||
|
** fields do not contain the expected values) and the conflict handler
|
||||||
|
** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation,
|
||||||
|
** but pass NULL as the final argument so that sessionApplyOneOp() ignores
|
||||||
|
** the SQLITE_CHANGESET_DATA problem. */
|
||||||
|
if( bRetry ){
|
||||||
|
assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE );
|
||||||
|
rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bReplace ){
|
/* If the bReplace flag is set, the change is an INSERT that has not
|
||||||
|
** been performed because the database already contains a row with the
|
||||||
|
** specified primary key and the conflict handler returned
|
||||||
|
** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row
|
||||||
|
** before reattempting the INSERT. */
|
||||||
|
else if( bReplace ){
|
||||||
assert( pIter->op==SQLITE_INSERT );
|
assert( pIter->op==SQLITE_INSERT );
|
||||||
rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
|
rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
@ -3968,6 +3992,7 @@ static int sessionChangesetApply(
|
|||||||
const char *zTab = 0; /* Name of current table */
|
const char *zTab = 0; /* Name of current table */
|
||||||
int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
|
int nTab = 0; /* Result of sqlite3Strlen30(zTab) */
|
||||||
SessionApplyCtx sApply; /* changeset_apply() context object */
|
SessionApplyCtx sApply; /* changeset_apply() context object */
|
||||||
|
int bPatchset;
|
||||||
|
|
||||||
assert( xConflict!=0 );
|
assert( xConflict!=0 );
|
||||||
|
|
||||||
@ -4059,18 +4084,17 @@ static int sessionChangesetApply(
|
|||||||
rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx);
|
rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
bPatchset = pIter->bPatchset;
|
||||||
rc = sessionRetryConstraints(
|
|
||||||
db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = sqlite3changeset_finalize(pIter);
|
rc = sqlite3changeset_finalize(pIter);
|
||||||
}else{
|
}else{
|
||||||
sqlite3changeset_finalize(pIter);
|
sqlite3changeset_finalize(pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = sessionRetryConstraints(db, bPatchset, zTab, &sApply, xConflict, pCtx);
|
||||||
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
int nFk, notUsed;
|
int nFk, notUsed;
|
||||||
sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0);
|
sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0);
|
||||||
|
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
|||||||
C Enhanced\scomments\sdescribing\sthe\ssessions\sfile\sformat.\s\sNo\schanges\sto\scode.
|
C Add\sfurther\stests\sfor\sthe\scode\son\sthis\sbranch.\sFix\sa\sproblem\sin\sOOM\shandling.
|
||||||
D 2016-03-31T02:44:56.615
|
D 2016-03-31T10:50:26.149
|
||||||
F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449
|
F Makefile.in e812bb732d7af01baa09f1278bd4f4a2e3a09449
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998
|
F Makefile.msc cde766eb7c27a7ca42000e66c5f0c37a17a05998
|
||||||
@ -287,10 +287,11 @@ F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390
|
|||||||
F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2
|
F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2
|
||||||
F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
|
F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
|
||||||
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
|
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
|
||||||
F ext/session/sessionG.test 388b4f311176411301c35f90f0bf2cb7c6c3dec9
|
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
|
||||||
F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
|
F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
|
||||||
F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40
|
F ext/session/sessionfault.test d52cbb7bee48cc8ee80335e07eb72fcb6b15eb40
|
||||||
F ext/session/sqlite3session.c 8ed9c3acf81b12d9d6fcb61b198d851c06046555
|
F ext/session/sessionfault2.test 2667fec1452e46abb5ce6c9f99483de8e0559032
|
||||||
|
F ext/session/sqlite3session.c 2fc72bd989c424a15802da766c7ebd8eed47bcf6
|
||||||
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
|
F ext/session/sqlite3session.h 64e9e7f185725ef43b97f4a9a0c0df0669844f1d
|
||||||
F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce
|
F ext/session/test_session.c 187bd344c5ae9d5be85e22ef7c3010f0c17307ce
|
||||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||||
@ -1481,7 +1482,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P ea917c14b940f95b20b91dae77567dc25a651ef6
|
P 84dc41e2df1092e9724a535b670343181a9cd0dd
|
||||||
R 703150f896b886ff9303fa6318e268aa
|
R 6c1e5637abee98a737c22aa1d2e2c831
|
||||||
U drh
|
U dan
|
||||||
Z 55b5826bc78e3fc677b5c1348287f2c3
|
Z ca2c22d2a622b0edd20f5f5ca6a19e56
|
||||||
|
@ -1 +1 @@
|
|||||||
84dc41e2df1092e9724a535b670343181a9cd0dd
|
195f3340ee4d870420e4f58d44300bab5436b920
|
Reference in New Issue
Block a user