mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add experimental API sqlite3_db_cacheflush().
FossilOrigin-Name: 65b86dc1fa4a57cc3cde86a820d9f848aa288a15
This commit is contained in:
27
manifest
27
manifest
@ -1,5 +1,5 @@
|
||||
C Factor\sout\sadding\sNOT\sexpression\snodes\sin\sthe\sparser\sinto\sa\ssubroutine.
|
||||
D 2015-10-28T16:05:10.981
|
||||
C Add\sexperimental\sAPI\ssqlite3_db_cacheflush().
|
||||
D 2015-10-28T19:46:57.460
|
||||
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4
|
||||
@ -305,7 +305,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c 1cae029707c323292b5691e4d0a4c5c44561c877
|
||||
F src/main.c b9d020342b2a2b13808c6260792ef233d7af5b1d
|
||||
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
@ -327,8 +327,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c fc93d55f96bb978f0b0168c6ea7d6fc60b0e172c
|
||||
F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 2fbeeba28f4e6d08a15bc106f36c43346a81f09e
|
||||
F src/pager.h ac213f8143ebfee6a8bfb91cf4ca02c9a83343c5
|
||||
F src/pager.c 059991ce76b1a857cb84dd2469cfcfaaae1d77fa
|
||||
F src/pager.h 1c4fa826c330040c5659a384446c7cc6e8e4200c
|
||||
F src/parse.y 11078cd8e3af00f030505b6a86a06a4536cfdeaa
|
||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
@ -342,7 +342,7 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 167b4e9058bc8e997d18d6b6b20ecbb0c9c457af
|
||||
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in 070b49c253bd41607ec43505a16163aa4b537b83
|
||||
F src/sqlite.h.in e7da8d15141d0753bfe14945bd64592a42575c04
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h b1e72ffe282c91ae30a2bf403319126dbaebd556
|
||||
@ -350,7 +350,7 @@ F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
|
||||
F src/test1.c 8fff9c5aa63d6490f516d018b70c12a9cb9a4d8a
|
||||
F src/test1.c 9ac5cbfe3c859ab7518edc5109a2959d6bf7b059
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c f7ae1d6a4aa07aac257de18a43800c1199b513fc
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
@ -503,6 +503,7 @@ F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
|
||||
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test 95944e4210100c525ec301c060721e82210c33a5
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
@ -510,6 +511,7 @@ F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cffault.test 1383919788fa50db60f6119da5785c62fbc8b527
|
||||
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
@ -1395,7 +1397,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P a85c2a4758c27e8d5d0395751eb3cfd9985ce696
|
||||
R fb08eb2aea7ef14b6808d0fed46a7f2e
|
||||
U drh
|
||||
Z 776eb09f5d20f370f46eb3dbeaa8d2e2
|
||||
P 001854181640bd9b088f2bc16083d84808c3da18
|
||||
R 2dbc861fa3cf60b53d3ec06b17c9981a
|
||||
T *branch * cacheflush
|
||||
T *sym-cacheflush *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z c07109c8cca9fe678b00367209f93a20
|
||||
|
@ -1 +1 @@
|
||||
001854181640bd9b088f2bc16083d84808c3da18
|
||||
65b86dc1fa4a57cc3cde86a820d9f848aa288a15
|
33
src/main.c
33
src/main.c
@ -740,6 +740,39 @@ int sqlite3_db_release_memory(sqlite3 *db){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush any dirty pages in the pager-cache for any attached database
|
||||
** to disk.
|
||||
*/
|
||||
int sqlite3_db_cacheflush(sqlite3 *db){
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
int bSeenBusy = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
|
||||
Pager *pPager = sqlite3BtreePager(pBt);
|
||||
rc = sqlite3PagerFlush(pPager);
|
||||
if( rc==SQLITE_BUSY ){
|
||||
bSeenBusy = 1;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Configuration settings for an individual database connection
|
||||
*/
|
||||
|
17
src/pager.c
17
src/pager.c
@ -4473,6 +4473,23 @@ static int pagerStress(void *p, PgHdr *pPg){
|
||||
return pager_error(pPager, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush all unreferenced dirty pages to disk.
|
||||
*/
|
||||
int sqlite3PagerFlush(Pager *pPager){
|
||||
int rc = SQLITE_OK;
|
||||
PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
|
||||
|
||||
while( rc==SQLITE_OK && pList ){
|
||||
PgHdr *pNext = pList->pDirty;
|
||||
if( pList->nRef==0 ){
|
||||
rc = pagerStress((void*)pPager, pList);
|
||||
}
|
||||
pList = pNext;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate and initialize a new Pager object and put a pointer to it
|
||||
|
@ -132,6 +132,7 @@ int sqlite3PagerGetJournalMode(Pager*);
|
||||
int sqlite3PagerOkToChangeJournalMode(Pager*);
|
||||
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
|
||||
sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
|
||||
int sqlite3PagerFlush(Pager*);
|
||||
|
||||
/* Functions used to obtain and release page references. */
|
||||
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
|
||||
|
@ -7792,6 +7792,36 @@ int sqlite3_stmt_scanstatus(
|
||||
*/
|
||||
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flush caches to disk mid-transaction
|
||||
**
|
||||
** If a write-transaction is open when this function is called, any dirty
|
||||
** pages in the pager-cache that are not currently in use are written out
|
||||
** to disk. A dirty page may be in use if a database cursor created by an
|
||||
** active SQL statement is reading from it, or if it is page 1 of a database
|
||||
** file (page 1 is always "in use"). Dirty pages are flushed for all
|
||||
** databases - "main", "temp" and any attached databases.
|
||||
**
|
||||
** If this function needs to obtain extra database locks before dirty pages
|
||||
** can be flushed to disk, it does so. If said locks cannot be obtained
|
||||
** immediately and there is a busy-handler callback configured, it is invoked
|
||||
** in the usual manner. If the required lock still cannot be obtained, then
|
||||
** the database is skipped and an attempt made to flush any dirty pages
|
||||
** belonging to the next (if any) database. If any databases are skipped
|
||||
** because locks cannot be obtained, but no other error occurs, this
|
||||
** function returns SQLITE_BUSY.
|
||||
**
|
||||
** If any other error occurs while flushing dirty pages to disk (for
|
||||
** example an IO error or out-of-memory condition), then processing is
|
||||
** abandoned and an SQLite error code returned to the caller immediately.
|
||||
** In this case the open transaction may be automatically rolled back.
|
||||
**
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
**
|
||||
** This function does not set the database handle error code or message
|
||||
** returned by the sqlite3_errcode() and sqlite3_errmsg() functions.
|
||||
*/
|
||||
int sqlite3_db_cacheflush(sqlite3*);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
|
29
src/test1.c
29
src/test1.c
@ -4688,6 +4688,34 @@ static int test_db_release_memory(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_db_cacheflush DB
|
||||
**
|
||||
** Attempt to flush any dirty pages to disk.
|
||||
*/
|
||||
static int test_db_cacheflush(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
rc = sqlite3_db_cacheflush(db);
|
||||
if( rc ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_db_filename DB DBNAME
|
||||
**
|
||||
@ -6876,6 +6904,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
|
||||
{ "sqlite3_release_memory", test_release_memory, 0},
|
||||
{ "sqlite3_db_release_memory", test_db_release_memory, 0},
|
||||
{ "sqlite3_db_cacheflush", test_db_cacheflush, 0},
|
||||
{ "sqlite3_db_filename", test_db_filename, 0},
|
||||
{ "sqlite3_db_readonly", test_db_readonly, 0},
|
||||
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
||||
|
207
test/cacheflush.test
Normal file
207
test/cacheflush.test
Normal file
@ -0,0 +1,207 @@
|
||||
# 2011 November 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains test cases for sqlite3_db_cacheflush API.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cacheflush
|
||||
test_set_config_pagecache 0 0
|
||||
|
||||
# Run the supplied SQL on a copy of the database currently stored on
|
||||
# disk in file $dbfile.
|
||||
proc diskquery {dbfile sql} {
|
||||
forcecopy $dbfile dq.db
|
||||
sqlite3 dq dq.db
|
||||
set res [execsql $sql dq]
|
||||
dq close
|
||||
set res
|
||||
}
|
||||
|
||||
# Simplest possible test.
|
||||
#
|
||||
do_execsql_test 1.1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
do_test 1.1.1 {
|
||||
diskquery test.db { SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
do_test 1.1.2 {
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db { SELECT * FROM t1 }
|
||||
} {1 2 3 4}
|
||||
|
||||
# Test that multiple pages may be flushed to disk.
|
||||
#
|
||||
do_execsql_test 1.2.0 {
|
||||
COMMIT;
|
||||
CREATE TABLE t2(a, b);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t2 VALUES('a', 'b');
|
||||
}
|
||||
do_test 1.2.1 {
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {1 2 3 4}
|
||||
do_test 1.2.2 {
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {1 2 3 4 5 6 a b}
|
||||
|
||||
# Test that pages with nRef!=0 are not flushed to disk.
|
||||
#
|
||||
do_execsql_test 1.3.0 {
|
||||
COMMIT;
|
||||
CREATE TABLE t3(a, b);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t2 VALUES('c', 'd');
|
||||
INSERT INTO t3 VALUES('i', 'ii');
|
||||
}
|
||||
do_test 1.3.1 {
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 2 3 4 5 6 a b}
|
||||
do_test 1.3.2 {
|
||||
db eval { SELECT a FROM t1 } {
|
||||
if {$a==3} {
|
||||
sqlite3_db_cacheflush db
|
||||
}
|
||||
}
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 2 3 4 5 6 a b c d i ii}
|
||||
do_test 1.3.2 {
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 a b c d i ii}
|
||||
|
||||
# Check that SQLITE_BUSY is returned if pages cannot be flushed due to
|
||||
# conflicting read locks.
|
||||
#
|
||||
do_execsql_test 1.4.0 {
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
}
|
||||
do_test 1.4.1 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
do_test 1.4.2 {
|
||||
list [catch { sqlite3_db_cacheflush db } msg] $msg
|
||||
} {1 {database is locked}}
|
||||
do_test 1.4.3 {
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
do_test 1.4.4 {
|
||||
db2 close
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
do_execsql_test 1.4.5 { COMMIT }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that ATTACHed database caches are also flushed.
|
||||
#
|
||||
forcedelete test.db2
|
||||
do_execsql_test 2.1.0 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t4(x, y);
|
||||
INSERT INTO t4 VALUES('A', 'B');
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(11, 12);
|
||||
INSERT INTO t4 VALUES('C', 'D');
|
||||
}
|
||||
do_test 2.1.1 {
|
||||
diskquery test.db { SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
do_test 2.1.2 {
|
||||
diskquery test.db2 { SELECT * FROM t4; }
|
||||
} {A B}
|
||||
do_test 2.1.3 {
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db { SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
do_test 2.1.4 {
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db2 { SELECT * FROM t4; }
|
||||
} {A B C D}
|
||||
do_execsql_test 2.1.5 { COMMIT }
|
||||
|
||||
# And that hitting an SQLITE_BUSY when flushing "main" does not stop
|
||||
# SQLite from going on to flush "aux".
|
||||
#
|
||||
do_execsql_test 2.2.0 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(13, 14);
|
||||
INSERT INTO t4 VALUES('E', 'F');
|
||||
}
|
||||
do_test 2.2.1 {
|
||||
diskquery test.db { SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
do_test 2.2.2 {
|
||||
diskquery test.db2 { SELECT * FROM t4; }
|
||||
} {A B C D}
|
||||
do_test 2.2.3 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
list [catch { sqlite3_db_cacheflush db } msg] $msg
|
||||
} {1 {database is locked}}
|
||||
do_test 2.2.4 {
|
||||
diskquery test.db { SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
do_test 2.2.5 {
|
||||
diskquery test.db2 { SELECT * FROM t4; }
|
||||
} {A B C D E F}
|
||||
do_test 2.2.6 {
|
||||
db2 close
|
||||
sqlite3_db_cacheflush db
|
||||
diskquery test.db { SELECT * FROM t1; }
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
|
||||
do_execsql_test 2.2.7 { COMMIT }
|
||||
|
||||
test_restore_config_pagecache
|
||||
finish_test
|
||||
|
57
test/cffault.test
Normal file
57
test/cffault.test
Normal file
@ -0,0 +1,57 @@
|
||||
# 2011 November 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains fault-injection test cases for the
|
||||
# sqlite3_db_cacheflush API.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cacheflush
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# Run the supplied SQL on a copy of the database currently stored on
|
||||
# disk in file $dbfile.
|
||||
proc diskquery {dbfile sql} {
|
||||
forcecopy $dbfile dq.db
|
||||
sqlite3 dq dq.db
|
||||
set res [execsql $sql dq]
|
||||
dq close
|
||||
set res
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=b+1;
|
||||
}
|
||||
} -body {
|
||||
sqlite3_db_cacheflush db
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {disk I/O error}}
|
||||
catch { db eval COMMIT }
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
Reference in New Issue
Block a user