Postpone I/O associated with TEMP files for as long as possible, with the
hope that the I/O can ultimately be avoided completely. FossilOrigin-Name: 9d0a5ae00273686ea35b43bc2ffaa8775c176363
This commit is contained in:
commit
54606bbc14
34
manifest
34
manifest
@ -1,5 +1,5 @@
|
||||
C Modify\sthe\spermutations.test\sscript\sso\sas\sto\sset\sany\spermutation\sspecific\sconfiguration\svalues\sbefore\srunning\seach\sindividual\stest\sscript.\sFix\sa\smostly\sharmless\sbuffer\soverread\sin\sthe\ssessions\smodule.
|
||||
D 2016-04-29T11:33:58.662
|
||||
C Postpone\sI/O\sassociated\swith\sTEMP\sfiles\sfor\sas\slong\sas\spossible,\swith\sthe\nhope\sthat\sthe\sI/O\scan\sultimately\sbe\savoided\scompletely.
|
||||
D 2016-04-29T15:39:48.423
|
||||
F Makefile.in 9e816d0323e418fbc0f8b2c05fc14e0b3763d9e8
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
|
||||
@ -364,11 +364,11 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c 8422fba2eb592fbbb2d4006b6f2a67cad8951495
|
||||
F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c d20fa46d5beda38095be6070dd4c59e502817c72
|
||||
F src/pager.c a8d30c49c231e9a20d05257613db922532588963
|
||||
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
|
||||
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
|
||||
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
|
||||
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
|
||||
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
|
||||
F src/pcache.h 6b865be765d1ebd06145219550b10921c7da7cc9
|
||||
F src/pcache1.c 7f51d2b541aab57596adf62db2c4bb025d34f04d
|
||||
F src/pragma.c faf42922bb7ab2f6672cb550356c1967abae3c84
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
@ -389,7 +389,7 @@ F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060
|
||||
F src/test1.c ee8fd5c32acb93fb6fe885ca4801cfab85f5563f
|
||||
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
||||
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
|
||||
F src/test3.c 0df6f8dbb4cbaa7106397c70a271fa6a43659042
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 2c014d4977efd6107ec9eef3dfdec56ac516f824
|
||||
@ -512,7 +512,7 @@ F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
|
||||
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
|
||||
F test/backup.test dd4a5ff756e3df3931dacb1791db0584d4bad989
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
@ -553,7 +553,7 @@ F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
|
||||
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
@ -879,7 +879,7 @@ F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/loadext.test 42a3b8166dfcadcb0e0c8710dc520d97c31a8b98
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5
|
||||
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00
|
||||
F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12
|
||||
@ -968,7 +968,7 @@ F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
|
||||
F test/pagerfault.test 42ff797b1e6426c141cc7ee8b7417c9f27427950
|
||||
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
|
||||
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
|
||||
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
|
||||
@ -978,7 +978,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test b6b3e165fdc1b8c82a820033646dbfc6a7a01746
|
||||
F test/pragma.test dd5313eee9c6d9d4726593a68ede8768d3b50ccc
|
||||
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
@ -1111,7 +1111,9 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
|
||||
F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test c3d8c138f493207612960bbd6a8c50e84975e2ee
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl 30c7a9be8601d1c1c9c93d013545ebcb28d64254
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
@ -1484,8 +1486,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 4792d6dbba6857f74d27332dcc1468e39c767c71 89b0ee3351381f7bc666cb206f77a56f2e0d4a0e
|
||||
R 96866ed68b53e21043adf38fe4b23f76
|
||||
T +closed 89b0ee3351381f7bc666cb206f77a56f2e0d4a0e
|
||||
U dan
|
||||
Z 9ea5c0c266312c18cafe76aed2353dcd
|
||||
P 4cbd50245440e714935399a5c285cf32d8bfc424 b7bec7f2d3d08d0c14f77654be2c5cedf1619e58
|
||||
R f9ef4e1af8653e902d9192ffb04cabc2
|
||||
T +closed b7bec7f2d3d08d0c14f77654be2c5cedf1619e58
|
||||
U drh
|
||||
Z 20681342134be4241c18925dab8e4f41
|
||||
|
@ -1 +1 @@
|
||||
4cbd50245440e714935399a5c285cf32d8bfc424
|
||||
9d0a5ae00273686ea35b43bc2ffaa8775c176363
|
132
src/pager.c
132
src/pager.c
@ -872,6 +872,7 @@ static int assert_pager_state(Pager *p){
|
||||
** state.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
assert( !isOpen(p->fd) );
|
||||
assert( p->noSync );
|
||||
assert( p->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| p->journalMode==PAGER_JOURNALMODE_MEMORY
|
||||
@ -958,7 +959,7 @@ static int assert_pager_state(Pager *p){
|
||||
** back to OPEN state.
|
||||
*/
|
||||
assert( pPager->errCode!=SQLITE_OK );
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1170,6 +1171,8 @@ static int jrnlBufferSize(Pager *pPager){
|
||||
|
||||
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
|
||||
}
|
||||
#else
|
||||
# define jrnlBufferSize(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -1818,13 +1821,17 @@ static void pager_unlock(Pager *pPager){
|
||||
** it can safely move back to PAGER_OPEN state. This happens in both
|
||||
** normal and exclusive-locking mode.
|
||||
*/
|
||||
assert( pPager->errCode==SQLITE_OK || !MEMDB );
|
||||
if( pPager->errCode ){
|
||||
assert( !MEMDB );
|
||||
pager_reset(pPager);
|
||||
pPager->changeCountDone = pPager->tempFile;
|
||||
pPager->eState = PAGER_OPEN;
|
||||
pPager->errCode = SQLITE_OK;
|
||||
if( pPager->tempFile==0 ){
|
||||
pager_reset(pPager);
|
||||
pPager->changeCountDone = 0;
|
||||
pPager->eState = PAGER_OPEN;
|
||||
}else{
|
||||
pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
|
||||
}
|
||||
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
|
||||
pPager->errCode = SQLITE_OK;
|
||||
}
|
||||
|
||||
pPager->journalOff = 0;
|
||||
@ -1868,6 +1875,25 @@ static int pager_error(Pager *pPager, int rc){
|
||||
|
||||
static int pager_truncate(Pager *pPager, Pgno nPage);
|
||||
|
||||
/*
|
||||
** The write transaction open on the pager passed as the only argument is
|
||||
** being committed. This function returns true if all dirty pages should
|
||||
** be flushed to disk, or false otherwise. Pages should be flushed to disk
|
||||
** unless one of the following is true:
|
||||
**
|
||||
** * The db is an in-memory database.
|
||||
**
|
||||
** * The db is a temporary database and the db file has not been opened.
|
||||
**
|
||||
** * The db is a temporary database and the cache contains less than
|
||||
** C/4 dirty pages, where C is the configured cache-size.
|
||||
*/
|
||||
static int pagerFlushOnCommit(Pager *pPager){
|
||||
if( pPager->tempFile==0 ) return 1;
|
||||
if( !isOpen(pPager->fd) ) return 0;
|
||||
return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine ends a transaction. A transaction is usually ended by
|
||||
** either a COMMIT or a ROLLBACK operation. This routine may be called
|
||||
@ -2006,7 +2032,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
sqlite3BitvecDestroy(pPager->pInJournal);
|
||||
pPager->pInJournal = 0;
|
||||
pPager->nRec = 0;
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
if( MEMDB || pagerFlushOnCommit(pPager) ){
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
}else{
|
||||
sqlite3PcacheClearWritable(pPager->pPCache);
|
||||
}
|
||||
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
@ -2291,7 +2321,7 @@ static int pager_playback_one_page(
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
assert( pPg || !MEMDB );
|
||||
assert( pPager->eState!=PAGER_OPEN || pPg==0 );
|
||||
assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
|
||||
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
|
||||
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
|
||||
(isMainJrnl?"main-journal":"sub-journal")
|
||||
@ -2374,9 +2404,13 @@ static int pager_playback_one_page(
|
||||
** be written out into the database file before its journal file
|
||||
** segment is synced. If a crash occurs during or following this,
|
||||
** database corruption may ensue.
|
||||
**
|
||||
** Update: Another exception is for temp files that are not
|
||||
** in-memory databases. In this case the page may have been dirty
|
||||
** at the start of the transaction.
|
||||
*/
|
||||
assert( !pagerUseWal(pPager) );
|
||||
sqlite3PcacheMakeClean(pPg);
|
||||
if( pPager->tempFile==0 ) sqlite3PcacheMakeClean(pPg);
|
||||
}
|
||||
pager_set_pagehash(pPg);
|
||||
|
||||
@ -3168,6 +3202,8 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
*/
|
||||
assert( pPager->eState==PAGER_OPEN );
|
||||
assert( pPager->eLock>=SHARED_LOCK );
|
||||
assert( isOpen(pPager->fd) );
|
||||
assert( pPager->tempFile==0 );
|
||||
nPage = sqlite3WalDbsize(pPager->pWal);
|
||||
|
||||
/* If the number of pages in the database is not available from the
|
||||
@ -3175,14 +3211,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
** the database file. If the size of the database file is not an
|
||||
** integer multiple of the page-size, round up the result.
|
||||
*/
|
||||
if( nPage==0 ){
|
||||
if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
|
||||
i64 n = 0; /* Size of db file in bytes */
|
||||
assert( isOpen(pPager->fd) || pPager->tempFile );
|
||||
if( isOpen(pPager->fd) ){
|
||||
int rc = sqlite3OsFileSize(pPager->fd, &n);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
int rc = sqlite3OsFileSize(pPager->fd, &n);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
|
||||
}
|
||||
@ -4258,8 +4291,9 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
|
||||
|
||||
/* This function is only called for rollback pagers in WRITER_DBMOD state. */
|
||||
assert( !pagerUseWal(pPager) );
|
||||
assert( pPager->eState==PAGER_WRITER_DBMOD );
|
||||
assert( pPager->tempFile || pPager->eState==PAGER_WRITER_DBMOD );
|
||||
assert( pPager->eLock==EXCLUSIVE_LOCK );
|
||||
assert( isOpen(pPager->fd) || pList->pDirty==0 );
|
||||
|
||||
/* If the file is a temp-file has not yet been opened, open it now. It
|
||||
** is not possible for rc to be other than SQLITE_OK if this branch
|
||||
@ -4927,6 +4961,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
if( rc==SQLITE_OK && !locked ){
|
||||
Pgno nPage; /* Number of pages in database file */
|
||||
|
||||
assert( pPager->tempFile==0 );
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If the database is zero pages in size, that means that either (1) the
|
||||
@ -5019,17 +5054,17 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
/* This routine is only called from b-tree and only when there are no
|
||||
** outstanding pages. This implies that the pager state should either
|
||||
** be OPEN or READER. READER is only possible if the pager is or was in
|
||||
** exclusive access mode.
|
||||
*/
|
||||
** exclusive access mode. */
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
|
||||
assert( assert_pager_state(pPager) );
|
||||
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
|
||||
if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
|
||||
assert( pPager->errCode==SQLITE_OK );
|
||||
|
||||
if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
|
||||
int bHotJournal = 1; /* True if there exists a hot journal-file */
|
||||
|
||||
assert( !MEMDB );
|
||||
assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK );
|
||||
|
||||
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -5115,7 +5150,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = pagerSyncHotJournal(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_playback(pPager, 1);
|
||||
rc = pager_playback(pPager, !pPager->tempFile);
|
||||
pPager->eState = PAGER_OPEN;
|
||||
}
|
||||
}else if( !pPager->exclusiveMode ){
|
||||
@ -5211,7 +5246,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
rc = pagerBeginReadTransaction(pPager);
|
||||
}
|
||||
|
||||
if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
|
||||
if( pPager->tempFile==0 && pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
|
||||
rc = pagerPagecount(pPager, &pPager->dbSize);
|
||||
}
|
||||
|
||||
@ -5344,7 +5379,7 @@ int sqlite3PagerGet(
|
||||
);
|
||||
|
||||
if( rc==SQLITE_OK && pData ){
|
||||
if( pPager->eState>PAGER_READER ){
|
||||
if( pPager->eState>PAGER_READER || pPager->tempFile ){
|
||||
pPg = sqlite3PagerLookup(pPager, pgno);
|
||||
}
|
||||
if( pPg==0 ){
|
||||
@ -5411,7 +5446,8 @@ int sqlite3PagerGet(
|
||||
goto pager_acquire_err;
|
||||
}
|
||||
|
||||
if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
|
||||
assert( !isOpen(pPager->fd) || !MEMDB );
|
||||
if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){
|
||||
if( pgno>pPager->mxPgno ){
|
||||
rc = SQLITE_FULL;
|
||||
goto pager_acquire_err;
|
||||
@ -5553,24 +5589,24 @@ static int pager_open_journal(Pager *pPager){
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
|
||||
sqlite3MemJournalOpen(pPager->jfd);
|
||||
}else{
|
||||
const int flags = /* VFS flags to open journal file */
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
|
||||
(pPager->tempFile ?
|
||||
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
|
||||
(SQLITE_OPEN_MAIN_JOURNAL)
|
||||
);
|
||||
int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
int nSpill;
|
||||
|
||||
if( pPager->tempFile ){
|
||||
flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
|
||||
nSpill = sqlite3Config.nStmtSpill;
|
||||
}else{
|
||||
flags |= SQLITE_OPEN_MAIN_JOURNAL;
|
||||
nSpill = jrnlBufferSize(pPager);
|
||||
}
|
||||
|
||||
/* Verify that the database still has the same name as it did when
|
||||
** it was originally opened. */
|
||||
rc = databaseIsUnmoved(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
rc = sqlite3JournalOpen(
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
|
||||
rc = sqlite3JournalOpen (
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, nSpill
|
||||
);
|
||||
#else
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
|
||||
@ -5941,6 +5977,7 @@ int sqlite3PagerWrite(PgHdr *pPg){
|
||||
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
|
||||
return SQLITE_OK;
|
||||
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
assert( pPager->tempFile==0 );
|
||||
return pagerWriteLargeSector(pPg);
|
||||
}else{
|
||||
return pager_write(pPg);
|
||||
@ -6173,17 +6210,21 @@ int sqlite3PagerCommitPhaseOne(
|
||||
/* If a prior error occurred, report that error again. */
|
||||
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
||||
|
||||
/* Provide the ability to easily simulate an I/O error during testing */
|
||||
if( (rc = sqlite3FaultSim(400))!=SQLITE_OK ) return rc;
|
||||
|
||||
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
|
||||
pPager->zFilename, zMaster, pPager->dbSize));
|
||||
|
||||
/* If no database changes have been made, return early. */
|
||||
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
|
||||
|
||||
if( MEMDB ){
|
||||
assert( MEMDB==0 || pPager->tempFile );
|
||||
assert( isOpen(pPager->fd) || pPager->tempFile );
|
||||
if( 0==pagerFlushOnCommit(pPager) ){
|
||||
/* If this is an in-memory db, or no pages have been written to, or this
|
||||
** function has already been called, it is mostly a no-op. However, any
|
||||
** backup in progress needs to be restarted.
|
||||
*/
|
||||
** backup in progress needs to be restarted. */
|
||||
sqlite3BackupRestart(pPager->pBackup);
|
||||
}else{
|
||||
if( pagerUseWal(pPager) ){
|
||||
@ -6522,10 +6563,10 @@ void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if this is an in-memory pager.
|
||||
** Return true if this is an in-memory or temp-file backed pager.
|
||||
*/
|
||||
int sqlite3PagerIsMemdb(Pager *pPager){
|
||||
return MEMDB;
|
||||
return pPager->tempFile;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -6805,7 +6846,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
/* In order to be able to rollback, an in-memory database must journal
|
||||
** the page we are moving from.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
rc = sqlite3PagerWrite(pPg);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
@ -6862,7 +6903,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
assert( !pPgOld || pPgOld->nRef==1 );
|
||||
if( pPgOld ){
|
||||
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
/* Do not discard pages from an in-memory database since we might
|
||||
** need to rollback later. Just move the page out of the way. */
|
||||
sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
|
||||
@ -6879,7 +6920,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
** to exist, in case the transaction needs to roll back. Use pPgOld
|
||||
** as the original page since it has already been allocated.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
if( pPager->tempFile ){
|
||||
assert( pPgOld );
|
||||
sqlite3PcacheMove(pPgOld, origPgno);
|
||||
sqlite3PagerUnrefNotNull(pPgOld);
|
||||
@ -7132,7 +7173,8 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
|
||||
** Unless this is an in-memory or temporary database, clear the pager cache.
|
||||
*/
|
||||
void sqlite3PagerClearCache(Pager *pPager){
|
||||
if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
|
||||
assert( MEMDB==0 || pPager->tempFile );
|
||||
if( pPager->tempFile==0 ) pager_reset(pPager);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
26
src/pcache.c
26
src/pcache.c
@ -254,7 +254,7 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
|
||||
|
||||
/*
|
||||
** If the sqlite3PcacheFetch() routine is unable to allocate a new
|
||||
** page because new clean pages are available for reuse and the cache
|
||||
** page because no clean pages are available for reuse and the cache
|
||||
** size limit has been reached, then this routine can be invoked to
|
||||
** try harder to allocate a page. This routine might invoke the stress
|
||||
** callback to spill dirty pages to the journal. It will then try to
|
||||
@ -439,6 +439,17 @@ void sqlite3PcacheCleanAll(PCache *pCache){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
|
||||
*/
|
||||
void sqlite3PcacheClearWritable(PCache *pCache){
|
||||
PgHdr *p;
|
||||
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
||||
p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
|
||||
}
|
||||
pCache->pSynced = pCache->pDirtyTail;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
|
||||
*/
|
||||
@ -484,7 +495,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
|
||||
** it must be that pgno==0.
|
||||
*/
|
||||
assert( p->pgno>0 );
|
||||
if( ALWAYS(p->pgno>pgno) ){
|
||||
if( p->pgno>pgno ){
|
||||
assert( p->flags&PGHDR_DIRTY );
|
||||
sqlite3PcacheMakeClean(p);
|
||||
}
|
||||
@ -675,6 +686,17 @@ void sqlite3PcacheShrink(PCache *pCache){
|
||||
*/
|
||||
int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
|
||||
|
||||
/*
|
||||
** Return the number of dirty pages currently in the cache, as a percentage
|
||||
** of the configured cache size.
|
||||
*/
|
||||
int sqlite3PCachePercentDirty(PCache *pCache){
|
||||
PgHdr *pDirty;
|
||||
int nDirty = 0;
|
||||
int nCache = numberOfCachePages(pCache);
|
||||
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
|
||||
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
|
@ -99,6 +99,7 @@ void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
|
||||
void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
|
||||
void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
|
||||
void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
|
||||
void sqlite3PcacheClearWritable(PCache*);
|
||||
|
||||
/* Change a page number. Used by incr-vacuum. */
|
||||
void sqlite3PcacheMove(PgHdr*, Pgno);
|
||||
@ -173,4 +174,7 @@ void sqlite3PCacheSetDefault(void);
|
||||
int sqlite3HeaderSizePcache(void);
|
||||
int sqlite3HeaderSizePcache1(void);
|
||||
|
||||
/* Number of dirty pages as a percentage of the configured cache size */
|
||||
int sqlite3PCachePercentDirty(PCache*);
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
@ -547,7 +547,7 @@ static int btree_from_db(
|
||||
/*
|
||||
** Usage: btree_ismemdb ID
|
||||
**
|
||||
** Return true if the B-Tree is in-memory.
|
||||
** Return true if the B-Tree is currently stored entirely in memory.
|
||||
*/
|
||||
static int btree_ismemdb(
|
||||
void *NotUsed,
|
||||
@ -557,6 +557,7 @@ static int btree_ismemdb(
|
||||
){
|
||||
Btree *pBt;
|
||||
int res;
|
||||
sqlite3_file *pFile;
|
||||
|
||||
if( argc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
@ -566,7 +567,8 @@ static int btree_ismemdb(
|
||||
pBt = sqlite3TestTextToPtr(argv[1]);
|
||||
sqlite3_mutex_enter(pBt->db->mutex);
|
||||
sqlite3BtreeEnter(pBt);
|
||||
res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
|
||||
pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
|
||||
res = (pFile->pMethods==0);
|
||||
sqlite3BtreeLeave(pBt);
|
||||
sqlite3_mutex_leave(pBt->db->mutex);
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
|
||||
|
@ -164,7 +164,7 @@ foreach zOpenScript [list {
|
||||
set file_dest temp
|
||||
}] {
|
||||
foreach rows_dest {0 3 10} {
|
||||
foreach pgsz_dest {512 1024 2048} {
|
||||
foreach pgsz_dest {512 1024 2048 4096} {
|
||||
foreach nPagePerStep {1 200} {
|
||||
|
||||
# Open the databases.
|
||||
@ -176,17 +176,16 @@ foreach nPagePerStep {1 200} {
|
||||
# in-memory destination is only possible if the initial destination
|
||||
# page size is the same as the source page size (in this case 1024 bytes).
|
||||
#
|
||||
set isMemDest [expr {
|
||||
$zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
|
||||
}]
|
||||
set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
|
||||
|
||||
if { $isMemDest==0 || $pgsz_dest == 1024 } {
|
||||
if 0 {
|
||||
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
|
||||
puts -nonewline " (as $db_dest.$file_dest)"
|
||||
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
|
||||
puts ""
|
||||
}
|
||||
if 0 {
|
||||
puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
|
||||
puts -nonewline " (as $db_dest.$file_dest)"
|
||||
puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
|
||||
puts ""
|
||||
}
|
||||
|
||||
if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
|
||||
|
||||
# Set up the content of the source database.
|
||||
execsql {
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix cacheflush
|
||||
set testprefix cffault
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# Run the supplied SQL on a copy of the database currently stored on
|
||||
|
@ -423,8 +423,9 @@ do_test lock-6.5 {
|
||||
# * there exists one or more active read-only statements, and
|
||||
# * a transaction that modified zero database pages is committed.
|
||||
#
|
||||
set temp_status unlocked
|
||||
if {$TEMP_STORE>=2} {set temp_status unknown}
|
||||
#set temp_status unlocked
|
||||
#if {$TEMP_STORE>=2} {set temp_status unknown}
|
||||
set temp_status unknown
|
||||
do_test lock-7.1 {
|
||||
set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
|
||||
sqlite3_step $STMT
|
||||
|
@ -684,22 +684,24 @@ do_faultsim_test pagerfault-14a -prep {
|
||||
# is not possible to change the page-size of an in-memory database. Even
|
||||
# using the backup API.
|
||||
#
|
||||
if {$TEMP_STORE<2} {
|
||||
do_faultsim_test pagerfault-14b -prep {
|
||||
catch { db2 close }
|
||||
faultsim_restore_and_reopen
|
||||
# Update: It is no longer possible to change the page size of any temp
|
||||
# database after it has been created.
|
||||
#
|
||||
do_faultsim_test pagerfault-14b -prep {
|
||||
catch { db2 close }
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3 db2 ""
|
||||
db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
|
||||
} -body {
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 200
|
||||
set rc [B finish]
|
||||
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
|
||||
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
|
||||
}
|
||||
} -body {
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 200
|
||||
set rc [B finish]
|
||||
if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
|
||||
if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {1 {attempt to write a readonly database}} \
|
||||
{1 {sqlite3_backup_init() failed}}
|
||||
}
|
||||
|
||||
do_faultsim_test pagerfault-14c -prep {
|
||||
|
@ -1083,7 +1083,20 @@ do_test pragma-8.2.15 {
|
||||
# "memory" or "disk" as appropriate.
|
||||
#
|
||||
proc check_temp_store {} {
|
||||
db eval {CREATE TEMP TABLE IF NOT EXISTS a(b)}
|
||||
db eval {
|
||||
PRAGMA temp.cache_size = 1;
|
||||
CREATE TEMP TABLE IF NOT EXISTS a(b);
|
||||
DELETE FROM a;
|
||||
INSERT INTO a VALUES(randomblob(1000));
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
INSERT INTO a SELECT * FROM a;
|
||||
}
|
||||
db eval {PRAGMA database_list} {
|
||||
if {$name=="temp"} {
|
||||
set bt [btree_from_db db 1]
|
||||
|
134
test/tempfault.test
Normal file
134
test/tempfault.test
Normal file
@ -0,0 +1,134 @@
|
||||
# 2016 April 11
|
||||
#
|
||||
# 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 tests for fault-injection when SQLite is used with
|
||||
# a temp file database.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix tempfault
|
||||
|
||||
# sqlite3_memdebug_vfs_oom_test 0
|
||||
|
||||
do_faultsim_test 1 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
} -body {
|
||||
execsql { INSERT INTO t1 VALUES(5, 6) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
set rc [catch { execsql { SELECT * FROM t1 } } msg]
|
||||
if {$rc==0 && $msg != "1 2 3 4 5 6" && $msg != "1 2 3 4"} {
|
||||
error "data mismatch 1: $msg"
|
||||
}
|
||||
if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
|
||||
error "data mismatch 2: $msg"
|
||||
}
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
do_faultsim_test 2 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE t1 SET a = randomblob(99) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
do_faultsim_test 2.1 -faults * -prep {
|
||||
if {[info commands db]==""} {
|
||||
sqlite3 db ""
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
}
|
||||
} -body {
|
||||
execsql { UPDATE t1 SET a = randomblob(99) }
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = randomblob(99);
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
|
||||
ROLLBACK TO abc;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
faultsim_integrity_check db
|
||||
}
|
||||
|
||||
do_faultsim_test 4 -faults * -prep {
|
||||
sqlite3 db ""
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = randomblob(99);
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
|
||||
ROLLBACK TO abc;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
sqlite3_memdebug_vfs_oom_test 1
|
||||
finish_test
|
356
test/temptable2.test
Normal file
356
test/temptable2.test
Normal file
@ -0,0 +1,356 @@
|
||||
# 2016 March 3
|
||||
#
|
||||
# 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
|
||||
set testprefix temptable2
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100000 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM X;
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
PRAGMA temp.integrity_check;
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
SELECT * FROM t2;
|
||||
} {1 2 3 4}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
ROLLBACK;
|
||||
SELECT * FROM t2;
|
||||
} {1 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t1;
|
||||
} {1000}
|
||||
do_execsql_test 3.1.2 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
|
||||
ROLLBACK;
|
||||
}
|
||||
do_execsql_test 3.1.3 {
|
||||
SELECT count(*) FROM t1;
|
||||
} {1000}
|
||||
do_execsql_test 3.1.4 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==0;
|
||||
SAVEPOINT abc;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==1;
|
||||
ROLLBACK TO abc;
|
||||
UPDATE t1 SET b=randomblob(100) WHERE (rowid%10)==2;
|
||||
COMMIT;
|
||||
}
|
||||
do_execsql_test 3.2.2 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<10 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA temp.page_count;
|
||||
} {10 9}
|
||||
|
||||
do_execsql_test 4.1.2 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET b=randomblob(100);
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1.3 {
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
SELECT count(*) FROM t2;
|
||||
SELECT count(*) FROM t1;
|
||||
} {500 10}
|
||||
|
||||
do_test 4.1.4 {
|
||||
set n [db one { PRAGMA temp.page_count }]
|
||||
expr ($n >280 && $n < 300)
|
||||
} 1
|
||||
|
||||
do_execsql_test 4.1.4 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.1.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
|
||||
CREATE TEMP TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
|
||||
# Test that the temp database is now much bigger than the configured
|
||||
# cache size (10 pages).
|
||||
do_test 5.1.2 {
|
||||
set n [db one { PRAGMA temp.page_count }]
|
||||
expr ($n > 270 && $n < 290)
|
||||
} {1}
|
||||
|
||||
do_execsql_test 5.1.3 {
|
||||
BEGIN;
|
||||
UPDATE t1 SET a=2;
|
||||
UPDATE t2 SET a=randomblob(100);
|
||||
SELECT count(*) FROM t1;
|
||||
ROLLBACK;
|
||||
} {1}
|
||||
|
||||
do_execsql_test 5.1.4 {
|
||||
UPDATE t2 SET a=randomblob(100);
|
||||
|
||||
SELECT * FROM t1;
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 5.1.5 { PRAGMA temp.integrity_check } {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test this:
|
||||
#
|
||||
# 1. Page is DIRTY at the start of a transaction.
|
||||
# 2. Page is written out as part of the transaction.
|
||||
# 3. Page is then read back in.
|
||||
# 4. Transaction is rolled back. Is the page now clean or dirty?
|
||||
#
|
||||
# This actually does work. Step 4 marks the page as clean. But it also
|
||||
# writes to the database file itself. So marking it clean is correct -
|
||||
# the page does match the contents of the db file.
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
PRAGMA main.cache_size = 10;
|
||||
PRAGMA temp.cache_size = 10;
|
||||
|
||||
CREATE TEMP TABLE t1(x);
|
||||
INSERT INTO t1 VALUES('one');
|
||||
|
||||
CREATE TEMP TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
UPDATE t1 SET x='two'; -- step 1
|
||||
BEGIN;
|
||||
UPDATE t2 SET a=randomblob(100); -- step 2
|
||||
SELECT * FROM t1; -- step 3
|
||||
ROLLBACK; -- step 4
|
||||
|
||||
SELECT count(*) FROM t2;
|
||||
SELECT * FROM t1;
|
||||
} {two 500 two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
sqlite3 db ""
|
||||
do_execsql_test 7.1 {
|
||||
PRAGMA auto_vacuum=INCREMENTAL;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(zeroblob(900));
|
||||
INSERT INTO t1 VALUES(zeroblob(900));
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
INSERT INTO t1 SELECT x FROM t1;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE rowid%2;
|
||||
PRAGMA incremental_vacuum(4);
|
||||
ROLLBACK;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try changing the page size using a backup operation when pages are
|
||||
# stored in main-memory only.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.1 {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE INDEX i2 ON t2(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<20 )
|
||||
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
PRAGMA page_count;
|
||||
} {13}
|
||||
|
||||
do_test 8.2 {
|
||||
sqlite3 tmp ""
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
PRAGMA page_size = 8192;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<100 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
PRAGMA page_count;
|
||||
} tmp
|
||||
} {10}
|
||||
|
||||
do_test 8.3 {
|
||||
sqlite3_backup B tmp main db main
|
||||
B step 5
|
||||
B finish
|
||||
} {SQLITE_READONLY}
|
||||
|
||||
do_test 8.4 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
PRAGMA page_size;
|
||||
} tmp
|
||||
} {100 ok 8192}
|
||||
|
||||
do_test 8.5 {
|
||||
tmp eval { UPDATE t1 SET a=randomblob(100) }
|
||||
} {}
|
||||
|
||||
do_test 8.6 {
|
||||
sqlite3_backup B tmp main db main
|
||||
B step 1000
|
||||
B finish
|
||||
} {SQLITE_READONLY}
|
||||
|
||||
tmp close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try inserts and deletes with a large db in auto-vacuum mode. Check
|
||||
#
|
||||
foreach {tn mode} {
|
||||
1 delete
|
||||
2 wal
|
||||
} {
|
||||
reset_db
|
||||
sqlite3 db ""
|
||||
do_execsql_test 9.$tn.1.1 {
|
||||
PRAGMA cache_size = 15;
|
||||
PRAGMA auto_vacuum = 1;
|
||||
}
|
||||
execsql "PRAGMA journal_mode = $mode"
|
||||
|
||||
do_execsql_test 9.$tn.1.2 {
|
||||
CREATE TABLE tx(a, b);
|
||||
CREATE INDEX i1 ON tx(a);
|
||||
CREATE INDEX i2 ON tx(b);
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
for {set i 2} {$i<20} {incr i} {
|
||||
do_execsql_test 9.$tn.$i.1 { DELETE FROM tx WHERE (random()%3)==0 }
|
||||
|
||||
do_execsql_test 9.$tn.$i.2 { PRAGMA integrity_check } ok
|
||||
|
||||
do_execsql_test 9.$tn.$i.3 {
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<400 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.$i.4 { PRAGMA integrity_check } ok
|
||||
|
||||
do_execsql_test 9.$tn.$i.5 {
|
||||
BEGIN;
|
||||
DELETE FROM tx WHERE (random()%3)==0;
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO tx SELECT randomblob(100), randomblob(100) FROM x;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.$i.6 { PRAGMA integrity_check } ok
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# When using mmap mode with a temp file, SQLite must search the cache
|
||||
# before using a mapped page even when there is no write transaction
|
||||
# open. For a temp file, the on-disk version may not be up to date.
|
||||
#
|
||||
sqlite3 db ""
|
||||
do_execsql_test 10.0 {
|
||||
PRAGMA cache_size = 50;
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
BEGIN;
|
||||
WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 )
|
||||
INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
|
||||
COMMIT;
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
}
|
||||
|
||||
if {[permutation]!="journaltest"} {
|
||||
# The journaltest permutation does not support mmap, so this part of
|
||||
# the test is omitted.
|
||||
do_execsql_test 10.2 { PRAGMA mmap_size = 512000 } 512000
|
||||
}
|
||||
|
||||
do_execsql_test 10.3 { SELECT * FROM t2 } {1 2 3 4}
|
||||
do_execsql_test 10.4 { PRAGMA integrity_check } ok
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user