Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 76ea46c045 | |||
| 8e33b23089 | |||
| 1bfbdcbe6d | |||
| 03c8582307 | |||
| e7cad43368 | |||
| 09a982e4ce | |||
| 4a7eb4b545 | |||
| 34cf60ec74 | |||
| 8c24a369a5 | |||
| 0699966798 | |||
| e7d9f13d99 | |||
| 38deeb9763 | |||
| 5c531a4aab | |||
| f580860f51 | |||
| e712b5823e | |||
| 78c0eafb35 | |||
| 31b21295b0 | |||
| 2be25bffca | |||
| 0f2ab8db33 | |||
| de60fc2d87 | |||
| 43a6d4bd44 | |||
| 27e69643cf | |||
| c7f946297a | |||
| add995cc25 | |||
| 658dd586ed | |||
| 5b1626aa47 | |||
| e5077c1211 | |||
| 43795e3b0b | |||
| 9797706c04 | |||
| 73795becfe |
+3
-1
@@ -2600,7 +2600,9 @@ static int fts3SegReaderCursor(
|
||||
}
|
||||
|
||||
rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
|
||||
iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
|
||||
(isPrefix==0 && isScan==0),
|
||||
iStartBlock, iLeavesEndBlock,
|
||||
iEndBlock, zRoot, nRoot, &pSeg
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
|
||||
|
||||
+1
-1
@@ -401,7 +401,7 @@ int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
|
||||
int sqlite3Fts3PendingTermsFlush(Fts3Table *);
|
||||
void sqlite3Fts3PendingTermsClear(Fts3Table *);
|
||||
int sqlite3Fts3Optimize(Fts3Table *);
|
||||
int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
|
||||
int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
|
||||
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
|
||||
int sqlite3Fts3SegReaderPending(
|
||||
Fts3Table*,int,const char*,int,int,Fts3SegReader**);
|
||||
|
||||
+28
-8
@@ -110,6 +110,7 @@ struct Fts3DeferredToken {
|
||||
*/
|
||||
struct Fts3SegReader {
|
||||
int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
|
||||
int bLookup; /* True for a lookup only */
|
||||
|
||||
sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
|
||||
sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
|
||||
@@ -1088,6 +1089,18 @@ static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set an Fts3SegReader cursor to point at EOF.
|
||||
*/
|
||||
static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
|
||||
if( !fts3SegReaderIsRootOnly(pSeg) ){
|
||||
sqlite3_free(pSeg->aNode);
|
||||
sqlite3_blob_close(pSeg->pBlob);
|
||||
pSeg->pBlob = 0;
|
||||
}
|
||||
pSeg->aNode = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move the iterator passed as the first argument to the next term in the
|
||||
** segment. If successful, SQLITE_OK is returned. If there is no next term,
|
||||
@@ -1127,12 +1140,7 @@ static int fts3SegReaderNext(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
if( !fts3SegReaderIsRootOnly(pReader) ){
|
||||
sqlite3_free(pReader->aNode);
|
||||
sqlite3_blob_close(pReader->pBlob);
|
||||
pReader->pBlob = 0;
|
||||
}
|
||||
pReader->aNode = 0;
|
||||
fts3SegReaderSetEof(pReader);
|
||||
|
||||
/* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
|
||||
** blocks have already been traversed. */
|
||||
@@ -1379,6 +1387,7 @@ void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
|
||||
*/
|
||||
int sqlite3Fts3SegReaderNew(
|
||||
int iAge, /* Segment "age". */
|
||||
int bLookup, /* True for a lookup only */
|
||||
sqlite3_int64 iStartLeaf, /* First leaf to traverse */
|
||||
sqlite3_int64 iEndLeaf, /* Final leaf to traverse */
|
||||
sqlite3_int64 iEndBlock, /* Final block of segment */
|
||||
@@ -1401,6 +1410,7 @@ int sqlite3Fts3SegReaderNew(
|
||||
}
|
||||
memset(pReader, 0, sizeof(Fts3SegReader));
|
||||
pReader->iIdx = iAge;
|
||||
pReader->bLookup = bLookup;
|
||||
pReader->iStartBlock = iStartLeaf;
|
||||
pReader->iLeafEndBlock = iEndLeaf;
|
||||
pReader->iEndBlock = iEndBlock;
|
||||
@@ -2403,11 +2413,16 @@ static int fts3SegReaderStart(
|
||||
** b-tree leaf nodes contain more than one term.
|
||||
*/
|
||||
for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
|
||||
int res;
|
||||
Fts3SegReader *pSeg = pCsr->apSegment[i];
|
||||
do {
|
||||
int rc = fts3SegReaderNext(p, pSeg, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
|
||||
}while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );
|
||||
|
||||
if( pSeg->bLookup && res!=0 ){
|
||||
fts3SegReaderSetEof(pSeg);
|
||||
}
|
||||
}
|
||||
fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
|
||||
|
||||
@@ -2528,7 +2543,12 @@ int sqlite3Fts3SegReaderStep(
|
||||
** forward. Then sort the list in order of current term again.
|
||||
*/
|
||||
for(i=0; i<pCsr->nAdvance; i++){
|
||||
rc = fts3SegReaderNext(p, apSegment[i], 0);
|
||||
Fts3SegReader *pSeg = apSegment[i];
|
||||
if( pSeg->bLookup ){
|
||||
fts3SegReaderSetEof(pSeg);
|
||||
}else{
|
||||
rc = fts3SegReaderNext(p, pSeg, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Improvements\sto\sthe\sdocumentation\sof\sthe\ssqlite3_db_filename()\sinterface.
|
||||
D 2011-11-17T11:49:58.484
|
||||
C Fix\sthe\smultiplexor\slogging\sso\sthat\sit\sworks\swith\sSQLITE_ENABLE_8_3_NAMES.
|
||||
D 2012-04-04T13:51:22.547
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -63,9 +63,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c bd570b99f1f65b17d587361a421d7f2f28082aa0
|
||||
F ext/fts3/fts3.c 4cf7b8e5bbb6667f5d7818fa0bf064fbbb72b086
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h def7a900f98c5ab5fa4772e922bfa219d5097f05
|
||||
F ext/fts3/fts3Int.h ce958a6fa92a95462853aa3acc0b69bcda39102f
|
||||
F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691
|
||||
F ext/fts3/fts3_expr.c f5df26bddf46a5916b2a5f80c4027996e92b7b15
|
||||
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
|
||||
@@ -78,7 +78,7 @@ F ext/fts3/fts3_test.c 24fa13f330db011500acb95590da9eee24951894
|
||||
F ext/fts3/fts3_tokenizer.c 9ff7ec66ae3c5c0340fa081958e64f395c71a106
|
||||
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
|
||||
F ext/fts3/fts3_tokenizer1.c 0dde8f307b8045565cf63797ba9acfaff1c50c68
|
||||
F ext/fts3/fts3_write.c c097228bff4d33c6b8a270c9717b9f8339068776
|
||||
F ext/fts3/fts3_write.c cfb96f850c7bc86d901d143d0f8f8a642c910b10
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
|
||||
@@ -125,7 +125,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 4368158da74d4711888e03264105c5c527d76caf
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 80ea65224512884bb72976c93810d2dcaecc1353
|
||||
F src/btree.c 2fdde7d16c80bd4e8a0913038e766c4297818f6f
|
||||
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
||||
F src/btreeInt.h ea863a819224d3e6845ad1e39954d41558b8cd8b
|
||||
F src/build.c 8915bb6d72ead998f94c2756ea8d143c77709b70
|
||||
@@ -146,8 +146,8 @@ F src/insert.c 8f283d6734dd837ed7531b26d7622fda70874390
|
||||
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
|
||||
F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f
|
||||
F src/main.c 55cbc40465fb58708cb82d4a285a6ea8cf1e4581
|
||||
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
|
||||
F src/main.c e7e6985365795ef6c500d05d766222222efbb0ac
|
||||
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 7456e2ca0524609ebc06a9befeda5289d4575ad4
|
||||
@@ -163,12 +163,12 @@ F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
|
||||
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c 28bbdab2170dfce84d86c45456a18eab1d0f99a9
|
||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||
F src/os.h 3ee45fed34d174eabdafe27c659428a8a1ff973d
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
F src/os_unix.c 4fbb91726165e105c1679a2660f49a3f4c376e4f
|
||||
F src/os_win.c a22b88d2c088c09a678a471abafa8d60dbf56803
|
||||
F src/pager.c d981f3bfcc0e4460537d983899620700ccf8f539
|
||||
F src/os_unix.c baad28b27adc563579170b6d765af0b0cc1d98c8
|
||||
F src/os_win.c f954207e8ce20b2b587c44404334aa92ae905961
|
||||
F src/pager.c afadbdf1563265756c3d09f2f77f541d6a1cfa73
|
||||
F src/pager.h 5cd760857707529b403837d813d86b68938d6183
|
||||
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||
F src/pcache.c 1fdd77978c1525d1ca4b9ef48eb80abca710cb4c
|
||||
@@ -181,15 +181,15 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6
|
||||
F src/shell.c 29812a900a780eb0f835c4bc65e216272689def8
|
||||
F src/sqlite.h.in 19706a000717456c4963bb0f96262581436ffb5a
|
||||
F src/shell.c 92e96bf5e465d63c55c5fe7fca38228c67ce7682
|
||||
F src/sqlite.h.in 84cd7be33f5bf39329e018f93eb34b4a345c9c23
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h f412e020e1009163c74be56eaac1bf7f6c0a4515
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c de581e2e71f5e7f98366156afad83b4742ac6fe0
|
||||
F src/test1.c a445a5d09f63ca66a704720dbec240c65806bcd1
|
||||
F src/test1.c d019682c4480d612e4eca73412011a120e1468db
|
||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
|
||||
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
|
||||
@@ -211,39 +211,39 @@ F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
|
||||
F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
|
||||
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
|
||||
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
||||
F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
|
||||
F src/test_journal.c 2c06e4be6584d51b935dc8b353980a9388de62ef
|
||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
|
||||
F src/test_multiplex.c 3fc368022c46fe44ec22c5e1ed727223a54a6a1d
|
||||
F src/test_multiplex.c 42967feac8203afd180e2faa6fd1efd4191f85e2
|
||||
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
|
||||
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
||||
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
|
||||
F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
|
||||
F src/test_osinst.c 6abf0a37ce831120c4ef1b913afdd813e7ac1a73
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c a391c866217e92986c6f523f05b08aa6956c8419
|
||||
F src/test_quota.c ec7d1056936f69be953c343bcb480305ce8928f3
|
||||
F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
|
||||
F src/test_stat.c 69de4361c7a69fc1136d31ab7144408cd00805c7
|
||||
F src/test_stat.c 80271ad7d776a79babe0e025bb3a1bfcd3a3cfb1
|
||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 35022393dd54d147b998b6b7f7e945b01114d666
|
||||
F src/test_vfs.c 27b7d9de40630f603b9e2cf9ef2a7c81d31c4515
|
||||
F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d
|
||||
F src/test_vfstrace.c 065c7270a614254b2c68fbc7ba8d1fb1d5cbc823
|
||||
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705
|
||||
F src/trigger.c 1cfb80e2290ef66ea89cb4e821caae65a02c0d56
|
||||
F src/update.c 25e046a8f69d5e557aabde2000487b8545509d8d
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 01238e2b0f24a14779181dbf991fe02620a80e31
|
||||
F src/util.c 343508d359df65685b62e63964a40e7af4cfbe05
|
||||
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
|
||||
F src/vdbe.c a7ab9993ec5a4d9479dc99671faec061fbf9b889
|
||||
F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
|
||||
F src/vdbeInt.h 9498fc98a2c9e349a4ef13455ff5a3e898f40176
|
||||
F src/vdbeapi.c 4dbba7f94f127f6ea8d2d0505ee1f98e5ffbf546
|
||||
F src/vdbeaux.c 45713a5f8f4f36195f503b30153ddef292323f88
|
||||
F src/vdbeaux.c 52ebf2a62d6b66ded536d0a2745f2236771097c7
|
||||
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
||||
F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
|
||||
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
|
||||
@@ -296,6 +296,7 @@ F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
|
||||
F test/bigfile.test a8ec8073a20207456dab01a29ad9cde42b0dd103
|
||||
F test/bigfile2.test f8e83eca9abef60692a34255a2ebcb96aff897fc
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
|
||||
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
|
||||
@@ -462,7 +463,7 @@ F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test e7b80272efcced57d1d087a9da5c690dd7c21fd9
|
||||
F test/fts3atoken.test 402ef2f7c2fb4b3d4fa0587df6441c1447e799b3
|
||||
F test/fts3auto.test c1a30b37002b7c764a96937fbc71065b73d69494
|
||||
F test/fts3auto.test 868a2afea308d7d8b45ef29fcf022644a9e6d662
|
||||
F test/fts3aux1.test 0b02743955d56fc0d4d66236a26177bd1b726de0
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
@@ -485,6 +486,7 @@ F test/fts3malloc.test b86ea33db9e8c58c0c2f8027a9fcadaf6a1568be
|
||||
F test/fts3matchinfo.test 6507fe1c342e542300d65ea637d4110eccf894e6
|
||||
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix2.test 477ca96e67f60745b7ac931cfa6e9b080c562da5
|
||||
F test/fts3query.test ef79d31fdb355d094baec1c1b24b60439a1fb8a2
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2
|
||||
@@ -605,7 +607,9 @@ F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test eafaa41b9133d7a2ded4641bbe5f340731d35a52
|
||||
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
|
||||
F test/multiplex.test 9df8bf738b3b97c718fceb3fadb30900ba494418
|
||||
F test/multiplex.test e08cc7177bd6d85990ee1d71100bb6c684c02256
|
||||
F test/multiplex2.test 896ff138d27688b68c894b8166606454ce915793
|
||||
F test/multiplex3.test e17b73e904dbd789de37192b6b94424e6f847bc3
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
|
||||
@@ -633,7 +637,7 @@ F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota.test 1c59a396e8f7b5d8466fa74b59f2aeb778d74f7a
|
||||
F test/quota.test e09a01ec974e04a2c4f1c7615005722725b5e131
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a
|
||||
@@ -976,7 +980,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P 4d3cf9e1d8ac356db5a708913f614e42a6a56b94
|
||||
R daa1b38027d3a49fc0c491c85b1f5a39
|
||||
P e6806f0dc6a06796700d805952f95e2cc18f0ea3
|
||||
R 36de029057c30e17d2fa1fff1aac580d
|
||||
U drh
|
||||
Z f65f1ce31dbae92bc408999ba5cab4af
|
||||
Z 7a6d88ce3643ba76bc132c1e4c6b20fc
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1c45b2a0c055f6fc5da9d00ae2e9171099d904d4
|
||||
627eff32a23ec676f7e87f6904981b3804e0e1f0
|
||||
+1
-1
@@ -3979,7 +3979,7 @@ static int accessPayload(
|
||||
u8 aSave[4];
|
||||
u8 *aWrite = &pBuf[-4];
|
||||
memcpy(aSave, aWrite, 4);
|
||||
rc = sqlite3OsRead(fd, aWrite, a+4, pBt->pageSize * (nextPage-1));
|
||||
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
|
||||
nextPage = get4byte(aWrite);
|
||||
memcpy(aWrite, aSave, 4);
|
||||
}else
|
||||
|
||||
+3
-2
@@ -625,6 +625,7 @@ void sqlite3_reset_auto_extension(void){
|
||||
void sqlite3AutoLoadExtensions(sqlite3 *db){
|
||||
int i;
|
||||
int go = 1;
|
||||
int rc;
|
||||
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
|
||||
wsdAutoextInit;
|
||||
@@ -647,8 +648,8 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){
|
||||
}
|
||||
sqlite3_mutex_leave(mutex);
|
||||
zErrmsg = 0;
|
||||
if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
|
||||
sqlite3Error(db, SQLITE_ERROR,
|
||||
if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){
|
||||
sqlite3Error(db, rc,
|
||||
"automatic extension loading failed: %s", zErrmsg);
|
||||
go = 0;
|
||||
}
|
||||
|
||||
+12
-5
@@ -239,8 +239,8 @@ int sqlite3_initialize(void){
|
||||
*/
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
|
||||
int SQLITE_EXTRA_INIT(void);
|
||||
rc = SQLITE_EXTRA_INIT();
|
||||
int SQLITE_EXTRA_INIT(const char*);
|
||||
rc = SQLITE_EXTRA_INIT(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -257,6 +257,10 @@ int sqlite3_initialize(void){
|
||||
*/
|
||||
int sqlite3_shutdown(void){
|
||||
if( sqlite3GlobalConfig.isInit ){
|
||||
#ifdef SQLITE_EXTRA_SHUTDOWN
|
||||
void SQLITE_EXTRA_SHUTDOWN(void);
|
||||
SQLITE_EXTRA_SHUTDOWN();
|
||||
#endif
|
||||
sqlite3_os_end();
|
||||
sqlite3_reset_auto_extension();
|
||||
sqlite3GlobalConfig.isInit = 0;
|
||||
@@ -2246,10 +2250,13 @@ static int openDatabase(
|
||||
/* Load automatic extensions - extensions that have been registered
|
||||
** using the sqlite3_automatic_extension() API.
|
||||
*/
|
||||
sqlite3AutoLoadExtensions(db);
|
||||
rc = sqlite3_errcode(db);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto opendb_out;
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3AutoLoadExtensions(db);
|
||||
rc = sqlite3_errcode(db);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto opendb_out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS1
|
||||
|
||||
@@ -100,6 +100,37 @@
|
||||
# define SQLITE_TEMPNAME_SIZE 200
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
** We ought to be able to determine if we are compiling for win98 or winNT
|
||||
** using the _WIN32_WINNT macro as follows:
|
||||
**
|
||||
** #if defined(_WIN32_WINNT)
|
||||
** # define SQLITE_OS_WINNT 1
|
||||
** #else
|
||||
** # define SQLITE_OS_WINNT 0
|
||||
** #endif
|
||||
**
|
||||
** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
|
||||
** so the above test does not work. We'll just assume that everything is
|
||||
** winNT unless the programmer explicitly says otherwise by setting
|
||||
** SQLITE_OS_WINNT to 0.
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
||||
# define SQLITE_OS_WINNT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WindowsCE - which has a much
|
||||
** reduced API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
# define SQLITE_OS_WINCE 1
|
||||
#else
|
||||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/* If the SET_FULLSYNC macro is not defined above, then make it
|
||||
** a no-op
|
||||
*/
|
||||
|
||||
+7
-1
@@ -206,6 +206,7 @@ struct UnixUnusedFd {
|
||||
typedef struct unixFile unixFile;
|
||||
struct unixFile {
|
||||
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
||||
sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
|
||||
unixInodeInfo *pInode; /* Info about locks on this inode */
|
||||
int h; /* The file descriptor */
|
||||
unsigned char eFileLock; /* The type of lock held on this fd */
|
||||
@@ -3533,6 +3534,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_VFSNAME: {
|
||||
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
/* The pager calls this method to signal that it has done
|
||||
** a rollback and that the database is therefore unchanged and
|
||||
@@ -4560,6 +4565,7 @@ static int fillInUnixFile(
|
||||
|
||||
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
|
||||
pNew->h = h;
|
||||
pNew->pVfs = pVfs;
|
||||
pNew->zPath = zFilename;
|
||||
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
|
||||
pNew->ctrlFlags = UNIXFILE_EXCL;
|
||||
@@ -4899,7 +4905,7 @@ static int findCreateFileMode(
|
||||
*/
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
while( nDb>0 && !sqlite3Isalnum(zPath[nDb]) ) nDb--;
|
||||
while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
|
||||
if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
|
||||
#else
|
||||
while( zPath[nDb]!='-' ){
|
||||
|
||||
+5
-1
@@ -181,7 +181,7 @@ static int sqlite3_os_type = 0;
|
||||
# define SQLITE_WIN32_HAS_ANSI
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE || defined(_WIN32_WINNT)
|
||||
#if SQLITE_OS_WINCE || SQLITE_OS_WINNT
|
||||
# define SQLITE_WIN32_HAS_WIDE
|
||||
#endif
|
||||
|
||||
@@ -2145,6 +2145,10 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_VFSNAME: {
|
||||
*(char**)pArg = sqlite3_mprintf("win32");
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_SYNC_OMITTED: {
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+6
-6
@@ -2485,7 +2485,7 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
|
||||
if( rc==SQLITE_OK && currentSize!=newSize ){
|
||||
if( currentSize>newSize ){
|
||||
rc = sqlite3OsTruncate(pPager->fd, newSize);
|
||||
}else{
|
||||
}else if( (currentSize+szPage)<=newSize ){
|
||||
char *pTmp = pPager->pTmpSpace;
|
||||
memset(pTmp, 0, szPage);
|
||||
testcase( (newSize-szPage) < currentSize );
|
||||
@@ -3074,7 +3074,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
nPage = (Pgno)(n / pPager->pageSize);
|
||||
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
|
||||
if( nPage==0 && n>0 ){
|
||||
nPage = 1;
|
||||
}
|
||||
@@ -3267,13 +3267,13 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
*/
|
||||
if( pSavepoint ){
|
||||
u32 ii; /* Loop counter */
|
||||
i64 offset = pSavepoint->iSubRec*(4+pPager->pageSize);
|
||||
i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
|
||||
|
||||
if( pagerUseWal(pPager) ){
|
||||
rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
|
||||
}
|
||||
for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
|
||||
assert( offset==ii*(4+pPager->pageSize) );
|
||||
assert( offset==(i64)ii*(4+pPager->pageSize) );
|
||||
rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
|
||||
}
|
||||
assert( rc!=SQLITE_DONE );
|
||||
@@ -3504,7 +3504,7 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pager_reset(pPager);
|
||||
pPager->dbSize = (Pgno)(nByte/pageSize);
|
||||
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
|
||||
pPager->pageSize = pageSize;
|
||||
sqlite3PageFree(pPager->pTmpSpace);
|
||||
pPager->pTmpSpace = pNew;
|
||||
@@ -4121,7 +4121,7 @@ static int subjournalPage(PgHdr *pPg){
|
||||
** write the journal record into the file. */
|
||||
if( rc==SQLITE_OK ){
|
||||
void *pData = pPg->pData;
|
||||
i64 offset = pPager->nSubRec*(4+pPager->pageSize);
|
||||
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
|
||||
char *pData2;
|
||||
|
||||
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
|
||||
|
||||
+59
-22
@@ -1396,6 +1396,7 @@ static char zHelp[] =
|
||||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".vfsname ?AUX? Print the name of the VFS stack\n"
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
|
||||
;
|
||||
|
||||
@@ -2335,10 +2336,22 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}else
|
||||
|
||||
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
|
||||
printf("SQLite %s %s\n",
|
||||
printf("SQLite %s %s\n" /*extra-version-info*/,
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
}else
|
||||
|
||||
if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
|
||||
const char *zDbName = nArg==2 ? azArg[1] : "main";
|
||||
char *zVfsName = 0;
|
||||
if( p->db ){
|
||||
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
|
||||
if( zVfsName ){
|
||||
printf("%s\n", zVfsName);
|
||||
sqlite3_free(zVfsName);
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
|
||||
int j;
|
||||
assert( nArg<=ArraySize(azArg) );
|
||||
@@ -2644,29 +2657,30 @@ static int process_sqliterc(
|
||||
** Show available command line options
|
||||
*/
|
||||
static const char zOptions[] =
|
||||
" -help show this message\n"
|
||||
" -init filename read/process named file\n"
|
||||
" -echo print commands before execution\n"
|
||||
" -[no]header turn headers on or off\n"
|
||||
" -bail stop after hitting an error\n"
|
||||
" -interactive force interactive I/O\n"
|
||||
" -batch force batch I/O\n"
|
||||
" -column set output mode to 'column'\n"
|
||||
" -cmd command run \"command\" before reading stdin\n"
|
||||
" -csv set output mode to 'csv'\n"
|
||||
" -echo print commands before execution\n"
|
||||
" -init filename read/process named file\n"
|
||||
" -[no]header turn headers on or off\n"
|
||||
" -help show this message\n"
|
||||
" -html set output mode to HTML\n"
|
||||
" -interactive force interactive I/O\n"
|
||||
" -line set output mode to 'line'\n"
|
||||
" -list set output mode to 'list'\n"
|
||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||
" -multiplex enable the multiplexor VFS\n"
|
||||
#endif
|
||||
" -nullvalue 'text' set text string for NULL values\n"
|
||||
" -separator 'x' set output field separator (|)\n"
|
||||
" -stats print memory stats before each finalize\n"
|
||||
" -nullvalue 'text' set text string for NULL values\n"
|
||||
" -version show SQLite version\n"
|
||||
" -vfs NAME use NAME as the default VFS\n"
|
||||
#ifdef SQLITE_ENABLE_VFSTRACE
|
||||
" -vfstrace enable tracing of all VFS calls\n"
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||
" -multiplex enable the multiplexor VFS\n"
|
||||
#endif
|
||||
;
|
||||
static void usage(int showDetail){
|
||||
fprintf(stderr,
|
||||
@@ -2729,19 +2743,22 @@ int main(int argc, char **argv){
|
||||
char *z;
|
||||
if( argv[i][0]!='-' ) break;
|
||||
z = argv[i];
|
||||
if( z[0]=='-' && z[1]=='-' ) z++;
|
||||
if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z,"-separator")==0
|
||||
|| strcmp(z,"-nullvalue")==0
|
||||
|| strcmp(z,"-cmd")==0
|
||||
){
|
||||
i++;
|
||||
}else if( strcmp(argv[i],"-init")==0 ){
|
||||
}else if( strcmp(z,"-init")==0 ){
|
||||
i++;
|
||||
zInitFile = argv[i];
|
||||
/* Need to check for batch mode here to so we can avoid printing
|
||||
** informational messages (like from process_sqliterc) before
|
||||
** we do the actual processing of arguments later in a second pass.
|
||||
*/
|
||||
}else if( strcmp(argv[i],"-batch")==0 ){
|
||||
}else if( strcmp(z,"-batch")==0 ){
|
||||
stdin_is_interactive = 0;
|
||||
}else if( strcmp(argv[i],"-heap")==0 ){
|
||||
}else if( strcmp(z,"-heap")==0 ){
|
||||
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
|
||||
int j, c;
|
||||
const char *zSize;
|
||||
@@ -2758,7 +2775,7 @@ int main(int argc, char **argv){
|
||||
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_VFSTRACE
|
||||
}else if( strcmp(argv[i],"-vfstrace")==0 ){
|
||||
}else if( strcmp(z,"-vfstrace")==0 ){
|
||||
extern int vfstrace_register(
|
||||
const char *zTraceName,
|
||||
const char *zOldVfsName,
|
||||
@@ -2769,11 +2786,11 @@ int main(int argc, char **argv){
|
||||
vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||
}else if( strcmp(argv[i],"-multiplex")==0 ){
|
||||
}else if( strcmp(z,"-multiplex")==0 ){
|
||||
extern int sqlite3_multiple_initialize(const char*,int);
|
||||
sqlite3_multiplex_initialize(0, 1);
|
||||
#endif
|
||||
}else if( strcmp(argv[i],"-vfs")==0 ){
|
||||
}else if( strcmp(z,"-vfs")==0 ){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
|
||||
if( pVfs ){
|
||||
sqlite3_vfs_register(pVfs, 1);
|
||||
@@ -2855,7 +2872,8 @@ int main(int argc, char **argv){
|
||||
}else if( strcmp(z,"-separator")==0 ){
|
||||
i++;
|
||||
if(i>=argc){
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n",
|
||||
Argv0, z);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -2864,7 +2882,8 @@ int main(int argc, char **argv){
|
||||
}else if( strcmp(z,"-nullvalue")==0 ){
|
||||
i++;
|
||||
if(i>=argc){
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n",
|
||||
Argv0, z);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -2899,8 +2918,26 @@ int main(int argc, char **argv){
|
||||
}else if( strcmp(z,"-multiplex")==0 ){
|
||||
i++;
|
||||
#endif
|
||||
}else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
|
||||
}else if( strcmp(z,"-help")==0 ){
|
||||
usage(1);
|
||||
}else if( strcmp(z,"-cmd")==0 ){
|
||||
if( i==argc-1 ) break;
|
||||
i++;
|
||||
z = argv[i];
|
||||
if( z[0]=='.' ){
|
||||
rc = do_meta_command(z, &data);
|
||||
if( rc && bail_on_error ) return rc;
|
||||
}else{
|
||||
open_db(&data);
|
||||
rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
|
||||
if( zErrMsg!=0 ){
|
||||
fprintf(stderr,"Error: %s\n", zErrMsg);
|
||||
if( bail_on_error ) return rc!=0 ? rc : 1;
|
||||
}else if( rc!=0 ){
|
||||
fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
|
||||
if( bail_on_error ) return rc;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
@@ -2932,7 +2969,7 @@ int main(int argc, char **argv){
|
||||
char *zHistory = 0;
|
||||
int nHistory;
|
||||
printf(
|
||||
"SQLite version %s %.19s\n"
|
||||
"SQLite version %s %.19s\n" /*extra-version-info*/
|
||||
"Enter \".help\" for instructions\n"
|
||||
"Enter SQL statements terminated with a \";\"\n",
|
||||
sqlite3_libversion(), sqlite3_sourceid()
|
||||
|
||||
@@ -771,6 +771,17 @@ struct sqlite3_io_methods {
|
||||
** a write transaction to indicate that, unless it is rolled back for some
|
||||
** reason, the entire database file will be overwritten by the current
|
||||
** transaction. This is used by VACUUM operations.
|
||||
**
|
||||
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
|
||||
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
|
||||
** final bottom-level VFS are written into memory obtained from
|
||||
** [sqlite3_malloc()] and the result is stored in the char* variable
|
||||
** that the fourth parameter of [sqlite3_file_control()] points to.
|
||||
** The caller is responsible for freeing the memory when done. As with
|
||||
** all file-control actions, there is no guarantee that this will actually
|
||||
** do anything. Callers should initialize the char* variable to a NULL
|
||||
** pointer in case this file-control is not implemented. This file-control
|
||||
** is intended for diagnostic use only.
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_GET_LOCKPROXYFILE 2
|
||||
@@ -783,6 +794,7 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
|
||||
#define SQLITE_FCNTL_PERSIST_WAL 10
|
||||
#define SQLITE_FCNTL_OVERWRITE 11
|
||||
#define SQLITE_FCNTL_VFSNAME 12
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
|
||||
+34
@@ -5209,6 +5209,39 @@ static int file_control_persist_wal(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** tclcmd: file_control_vfsname DB ?AUXDB?
|
||||
**
|
||||
** Return a string that describes the stack of VFSes.
|
||||
*/
|
||||
static int file_control_vfsname(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
const char *zDbName = "main";
|
||||
char *zVfsName = 0;
|
||||
|
||||
if( objc!=2 && objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( objc==3 ){
|
||||
zDbName = Tcl_GetString(objv[2]);
|
||||
}
|
||||
sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
|
||||
Tcl_AppendResult(interp, zVfsName, (char*)0);
|
||||
sqlite3_free(zVfsName);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_vfs_list
|
||||
**
|
||||
@@ -6032,6 +6065,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
|
||||
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
|
||||
{ "file_control_persist_wal", file_control_persist_wal, 0 },
|
||||
{ "file_control_vfsname", file_control_vfsname, 0 },
|
||||
{ "sqlite3_vfs_list", vfs_list, 0 },
|
||||
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
|
||||
|
||||
|
||||
+1
-1
@@ -391,7 +391,7 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
|
||||
while( rc==SQLITE_OK && iTrunk>0 ){
|
||||
u32 nLeaf;
|
||||
u32 iLeaf;
|
||||
sqlite3_int64 iOff = (iTrunk-1)*pMain->nPagesize;
|
||||
sqlite3_int64 iOff = (i64)(iTrunk-1)*pMain->nPagesize;
|
||||
rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff);
|
||||
nLeaf = decodeUint32(&aData[4]);
|
||||
for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){
|
||||
|
||||
+264
-217
@@ -81,6 +81,9 @@
|
||||
#define sqlite3_mutex_notheld(X) ((void)(X),1)
|
||||
#endif /* SQLITE_THREADSAFE==0 */
|
||||
|
||||
/* First chunk for rollback journal files */
|
||||
#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
|
||||
|
||||
|
||||
/************************ Shim Definitions ******************************/
|
||||
|
||||
@@ -96,26 +99,16 @@
|
||||
# define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
|
||||
#endif
|
||||
|
||||
/* Default limit on number of chunks. Care should be taken
|
||||
** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
|
||||
** format specifier. It may be changed by calling
|
||||
** the xFileControl() interface.
|
||||
/* This used to be the default limit on number of chunks, but
|
||||
** it is no longer enforced. There is currently no limit to the
|
||||
** number of chunks.
|
||||
**
|
||||
** May be changed by calling the xFileControl() interface.
|
||||
*/
|
||||
#ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
|
||||
# define SQLITE_MULTIPLEX_MAX_CHUNKS 32
|
||||
# define SQLITE_MULTIPLEX_MAX_CHUNKS 12
|
||||
#endif
|
||||
|
||||
/* If SQLITE_MULTIPLEX_EXT_OVWR is defined, the
|
||||
** last SQLITE_MULTIPLEX_EXT_SZ characters of the
|
||||
** filename will be overwritten, otherwise, the
|
||||
** multiplex extension is simply appended to the filename.
|
||||
** Ex. (undefined) test.db -> test.db01
|
||||
** (defined) test.db -> test.01
|
||||
** Chunk 0 does not have a modified extension.
|
||||
*/
|
||||
#define SQLITE_MULTIPLEX_EXT_FMT "%02d"
|
||||
#define SQLITE_MULTIPLEX_EXT_SZ 2
|
||||
|
||||
/************************ Object Definitions ******************************/
|
||||
|
||||
/* Forward declaration of all object types */
|
||||
@@ -140,7 +133,8 @@ struct multiplexGroup {
|
||||
int nName; /* Length of base filename */
|
||||
int flags; /* Flags used for original opening */
|
||||
unsigned int szChunk; /* Chunk size used for this group */
|
||||
int bEnabled; /* TRUE to use Multiplex VFS for this file */
|
||||
unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */
|
||||
unsigned char bTruncate; /* TRUE to enable truncation of databases */
|
||||
multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */
|
||||
};
|
||||
|
||||
@@ -224,68 +218,36 @@ static int multiplexStrlen30(const char *z){
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||
** hold at pOrigVfs->mxPathname characters. This function departs
|
||||
** from the traditional temporary name generation in the os_win
|
||||
** and os_unix VFS in several ways, but is necessary so that
|
||||
** the file name is known for temporary files (like those used
|
||||
** during vacuum.)
|
||||
**
|
||||
** N.B. This routine assumes your underlying VFS is ok with using
|
||||
** "/" as a directory seperator. This is the default for UNIXs
|
||||
** and is allowed (even mixed) for most versions of Windows.
|
||||
** Generate the file-name for chunk iChunk of the group with base name
|
||||
** zBase. The file-name is written to buffer zOut before returning. Buffer
|
||||
** zOut must be allocated by the caller so that it is at least (nBase+4)
|
||||
** bytes in size, where nBase is the length of zBase, not including the
|
||||
** nul-terminator.
|
||||
*/
|
||||
static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
|
||||
static char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i,j;
|
||||
int attempts = 0;
|
||||
int exists = 0;
|
||||
int rc = SQLITE_ERROR;
|
||||
|
||||
/* Check that the output buffer is large enough for
|
||||
** pVfs->mxPathname characters.
|
||||
*/
|
||||
if( pOrigVfs->mxPathname <= nBuf ){
|
||||
char *zTmp = sqlite3_malloc(pOrigVfs->mxPathname);
|
||||
if( zTmp==0 ) return SQLITE_NOMEM;
|
||||
|
||||
/* sqlite3_temp_directory should always be less than
|
||||
** pVfs->mxPathname characters.
|
||||
*/
|
||||
sqlite3_snprintf(pOrigVfs->mxPathname,
|
||||
zTmp,
|
||||
"%s/",
|
||||
sqlite3_temp_directory ? sqlite3_temp_directory : ".");
|
||||
rc = pOrigVfs->xFullPathname(pOrigVfs, zTmp, nBuf, zBuf);
|
||||
sqlite3_free(zTmp);
|
||||
if( rc ) return rc;
|
||||
|
||||
/* Check that the output buffer is large enough for the temporary file
|
||||
** name.
|
||||
*/
|
||||
j = multiplexStrlen30(zBuf);
|
||||
if( (j + 8 + 1 + 3 + 1) <= nBuf ){
|
||||
/* Make 3 attempts to generate a unique name. */
|
||||
do {
|
||||
attempts++;
|
||||
sqlite3_randomness(8, &zBuf[j]);
|
||||
for(i=0; i<8; i++){
|
||||
unsigned char uc = (unsigned char)zBuf[j+i];
|
||||
zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)];
|
||||
}
|
||||
memcpy(&zBuf[j+i], ".tmp", 5);
|
||||
rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
|
||||
} while ( (rc==SQLITE_OK) && exists && (attempts<3) );
|
||||
if( rc==SQLITE_OK && exists ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
static void multiplexFilename(
|
||||
const char *zBase, /* Filename for chunk 0 */
|
||||
int nBase, /* Size of zBase in bytes (without \0) */
|
||||
int flags, /* Flags used to open file */
|
||||
int iChunk, /* Chunk to generate filename for */
|
||||
char *zOut /* Buffer to write generated name to */
|
||||
){
|
||||
memcpy(zOut, zBase, nBase+1);
|
||||
if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
|
||||
int n = nBase;
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
int i;
|
||||
for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
|
||||
if( i>=n-4 ) n = i+1;
|
||||
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
/* The extensions on overflow files for main databases are 001, 002,
|
||||
** 003 and so forth. To avoid name collisions, add 400 to the
|
||||
** extensions of journal files so that they are 401, 402, 403, ....
|
||||
*/
|
||||
iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
|
||||
}
|
||||
#endif
|
||||
sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Compute the filename for the iChunk-th chunk
|
||||
@@ -301,50 +263,80 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
|
||||
pGroup->aReal = p;
|
||||
pGroup->nReal = iChunk+1;
|
||||
}
|
||||
if( pGroup->aReal[iChunk].z==0 ){
|
||||
if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
|
||||
char *z;
|
||||
int n = pGroup->nName;
|
||||
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 );
|
||||
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
|
||||
if( z==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memcpy(z, pGroup->zName, n+1);
|
||||
if( iChunk>0 ){
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
if( n>3 && z[n-3]=='.' ){
|
||||
n--;
|
||||
}else if( n>4 && z[n-4]=='.' ){
|
||||
n -= 2;
|
||||
}
|
||||
#endif
|
||||
sqlite3_snprintf(3,&z[n],"%02d",iChunk);
|
||||
}
|
||||
multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Translate an sqlite3_file* that is really a multiplexGroup* into
|
||||
** the sqlite3_file* for the underlying original VFS.
|
||||
**
|
||||
** For chunk 0, the pGroup->flags determines whether or not a new file
|
||||
** is created if it does not already exist. For chunks 1 and higher, the
|
||||
** file is created only if createFlag is 1.
|
||||
*/
|
||||
static sqlite3_file *multiplexSubOpen(
|
||||
multiplexGroup *pGroup,
|
||||
int iChunk,
|
||||
int *rc,
|
||||
int *pOutFlags
|
||||
multiplexGroup *pGroup, /* The multiplexor group */
|
||||
int iChunk, /* Which chunk to open. 0==original file */
|
||||
int *rc, /* Result code in and out */
|
||||
int *pOutFlags, /* Output flags */
|
||||
int createFlag /* True to create if iChunk>0 */
|
||||
){
|
||||
sqlite3_file *pSubOpen = 0;
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
/* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are
|
||||
** part of a database journal are named db.401, db.402, and so on. A
|
||||
** database may therefore not grow to larger than 400 chunks. Attempting
|
||||
** to open chunk 401 indicates the database is full. */
|
||||
if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
|
||||
sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName);
|
||||
*rc = SQLITE_FULL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
*rc = multiplexSubFilename(pGroup, iChunk);
|
||||
if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
|
||||
int flags, bExists;
|
||||
flags = pGroup->flags;
|
||||
if( createFlag ){
|
||||
flags |= SQLITE_OPEN_CREATE;
|
||||
}else if( iChunk==0 ){
|
||||
/* Fall through */
|
||||
}else if( pGroup->aReal[iChunk].z==0 ){
|
||||
return 0;
|
||||
}else{
|
||||
*rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z,
|
||||
SQLITE_ACCESS_EXISTS, &bExists);
|
||||
if( *rc || !bExists ){
|
||||
if( *rc ){
|
||||
sqlite3_log(*rc, "multiplexor.xAccess failure on %s",
|
||||
pGroup->aReal[iChunk].z);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
flags &= ~SQLITE_OPEN_CREATE;
|
||||
}
|
||||
pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
|
||||
if( pSubOpen==0 ){
|
||||
*rc = SQLITE_NOMEM;
|
||||
*rc = SQLITE_IOERR_NOMEM;
|
||||
return 0;
|
||||
}
|
||||
pGroup->aReal[iChunk].p = pSubOpen;
|
||||
*rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
|
||||
pGroup->flags, pOutFlags);
|
||||
if( *rc!=SQLITE_OK ){
|
||||
flags, pOutFlags);
|
||||
if( (*rc)!=SQLITE_OK ){
|
||||
sqlite3_log(*rc, "multiplexor.xOpen failure on %s",
|
||||
pGroup->aReal[iChunk].z);
|
||||
sqlite3_free(pSubOpen);
|
||||
pGroup->aReal[iChunk].p = 0;
|
||||
return 0;
|
||||
@@ -353,6 +345,25 @@ static sqlite3_file *multiplexSubOpen(
|
||||
return pSubOpen;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size, in bytes, of chunk number iChunk. If that chunk
|
||||
** does not exist, then return 0. This function does not distingish between
|
||||
** non-existant files and zero-length files.
|
||||
*/
|
||||
static sqlite3_int64 multiplexSubSize(
|
||||
multiplexGroup *pGroup, /* The multiplexor group */
|
||||
int iChunk, /* Which chunk to open. 0==original file */
|
||||
int *rc /* Result code in and out */
|
||||
){
|
||||
sqlite3_file *pSub;
|
||||
sqlite3_int64 sz = 0;
|
||||
|
||||
pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
|
||||
if( pSub==0 ) return 0;
|
||||
*rc = pSub->pMethods->xFileSize(pSub, &sz);
|
||||
return sz;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the implementation of the multiplex_control() SQL function.
|
||||
*/
|
||||
@@ -420,7 +431,9 @@ static void multiplexSubClose(
|
||||
sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
|
||||
if( pSubOpen ){
|
||||
pSubOpen->pMethods->xClose(pSubOpen);
|
||||
if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
||||
if( pOrigVfs && pGroup->aReal[iChunk].z ){
|
||||
pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
||||
}
|
||||
sqlite3_free(pGroup->aReal[iChunk].p);
|
||||
}
|
||||
sqlite3_free(pGroup->aReal[iChunk].z);
|
||||
@@ -466,6 +479,7 @@ static int multiplexOpen(
|
||||
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
memset(pConn, 0, pVfs->szOsFile);
|
||||
assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) );
|
||||
|
||||
/* We need to create a group structure and manage
|
||||
** access to this group of files.
|
||||
@@ -473,23 +487,9 @@ static int multiplexOpen(
|
||||
multiplexEnter();
|
||||
pMultiplexOpen = (multiplexConn*)pConn;
|
||||
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
** temporary file name to use. This will be handled by the
|
||||
** original xOpen method. We just need to allocate space for
|
||||
** it.
|
||||
*/
|
||||
if( !zName ){
|
||||
zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 );
|
||||
if( zName==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* allocate space for group */
|
||||
nName = multiplexStrlen30(zName);
|
||||
nName = zName ? multiplexStrlen30(zName) : 0;
|
||||
sz = sizeof(multiplexGroup) /* multiplexGroup */
|
||||
+ nName + 1; /* zName */
|
||||
pGroup = sqlite3_malloc( sz );
|
||||
@@ -500,62 +500,100 @@ static int multiplexOpen(
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* assign pointers to extra space allocated */
|
||||
char *p = (char *)&pGroup[1];
|
||||
pMultiplexOpen->pGroup = pGroup;
|
||||
memset(pGroup, 0, sz);
|
||||
pMultiplexOpen->pGroup = pGroup;
|
||||
pGroup->bEnabled = -1;
|
||||
pGroup->bTruncate = (flags & SQLITE_OPEN_MAIN_DB)==0;
|
||||
pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
|
||||
if( flags & SQLITE_OPEN_URI ){
|
||||
const char *zChunkSize;
|
||||
zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
|
||||
if( zChunkSize ){
|
||||
unsigned int n = 0;
|
||||
int i;
|
||||
for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
|
||||
n = n*10 + zChunkSize[i] - '0';
|
||||
}
|
||||
if( n>0 ){
|
||||
pGroup->szChunk = (n+0xffff)&~0xffff;
|
||||
}else{
|
||||
/* A zero or negative chunksize disabled the multiplexor */
|
||||
pGroup->bEnabled = 0;
|
||||
|
||||
if( zName ){
|
||||
char *p = (char *)&pGroup[1];
|
||||
if( flags & SQLITE_OPEN_URI ){
|
||||
const char *zChunkSize;
|
||||
zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
|
||||
if( zChunkSize ){
|
||||
unsigned int n = 0;
|
||||
int i;
|
||||
for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
|
||||
n = n*10 + zChunkSize[i] - '0';
|
||||
}
|
||||
if( n>0 ){
|
||||
pGroup->szChunk = (n+0xffff)&~0xffff;
|
||||
}else{
|
||||
/* A zero or negative chunksize disabled the multiplexor */
|
||||
pGroup->bEnabled = 0;
|
||||
}
|
||||
}
|
||||
if( sqlite3_uri_parameter(zName, "truncate") ) pGroup->bTruncate = 1;
|
||||
}
|
||||
pGroup->zName = p;
|
||||
memcpy(pGroup->zName, zName, nName+1);
|
||||
pGroup->nName = nName;
|
||||
}
|
||||
if( pGroup->bEnabled ){
|
||||
/* Make sure that the chunksize is not such that the pending byte
|
||||
** falls at the end of a chunk. A region of up to 64K following
|
||||
** the pending byte is never written, so if the pending byte occurs
|
||||
** near the end of a chunk, that chunk will be too small. */
|
||||
extern int sqlite3PendingByte;
|
||||
while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
|
||||
pGroup->szChunk += 65536;
|
||||
}
|
||||
}
|
||||
pGroup->zName = p;
|
||||
/* save off base filename, name length, and original open flags */
|
||||
memcpy(pGroup->zName, zName, nName+1);
|
||||
pGroup->nName = nName;
|
||||
pGroup->flags = flags;
|
||||
rc = multiplexSubFilename(pGroup, 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
|
||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
|
||||
if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
|
||||
}
|
||||
if( pSubOpen ){
|
||||
int exists, rc2, rc3;
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_int64 sz;
|
||||
|
||||
rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
if( rc2==SQLITE_OK ){
|
||||
/* If the first overflow file exists and if the size of the main file
|
||||
** is different from the chunk size, that means the chunk size is set
|
||||
** set incorrectly. So fix it.
|
||||
**
|
||||
** Or, if the first overflow file does not exist and the main file is
|
||||
** larger than the chunk size, that means the chunk size is too small.
|
||||
** But we have no way of determining the intended chunk size, so
|
||||
** just disable the multiplexor all togethre.
|
||||
*/
|
||||
rc3 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
||||
SQLITE_ACCESS_EXISTS, &exists);
|
||||
if( rc3==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
|
||||
&& sz!=pGroup->szChunk ){
|
||||
pGroup->szChunk = sz;
|
||||
}else if( rc3==SQLITE_OK && !exists && sz>pGroup->szChunk ){
|
||||
pGroup->bEnabled = 0;
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
if( rc==SQLITE_OK && zName ){
|
||||
int bExists;
|
||||
if( sz==0 ){
|
||||
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
/* If opening a main journal file and the first chunk is zero
|
||||
** bytes in size, delete any subsequent chunks from the
|
||||
** file-system. */
|
||||
int iChunk = 1;
|
||||
do {
|
||||
rc = pOrigVfs->xAccess(pOrigVfs,
|
||||
pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
|
||||
);
|
||||
if( rc==SQLITE_OK && bExists ){
|
||||
rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = multiplexSubFilename(pGroup, ++iChunk);
|
||||
}
|
||||
}
|
||||
}while( rc==SQLITE_OK && bExists );
|
||||
}
|
||||
}else{
|
||||
/* If the first overflow file exists and if the size of the main file
|
||||
** is different from the chunk size, that means the chunk size is set
|
||||
** set incorrectly. So fix it.
|
||||
**
|
||||
** Or, if the first overflow file does not exist and the main file is
|
||||
** larger than the chunk size, that means the chunk size is too small.
|
||||
** But we have no way of determining the intended chunk size, so
|
||||
** just disable the multiplexor all togethre.
|
||||
*/
|
||||
rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
||||
SQLITE_ACCESS_EXISTS, &bExists);
|
||||
bExists = multiplexSubSize(pGroup, 1, &rc)>0;
|
||||
if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
|
||||
&& sz!=pGroup->szChunk ){
|
||||
pGroup->szChunk = sz;
|
||||
}else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
|
||||
pGroup->bEnabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pSubOpen->pMethods->iVersion==1 ){
|
||||
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
|
||||
}else{
|
||||
@@ -584,8 +622,33 @@ static int multiplexDelete(
|
||||
const char *zName, /* Name of file to delete */
|
||||
int syncDir
|
||||
){
|
||||
int rc;
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||
return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
|
||||
rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If the main chunk was deleted successfully, also delete any subsequent
|
||||
** chunks - starting with the last (highest numbered).
|
||||
*/
|
||||
int nName = strlen(zName);
|
||||
char *z;
|
||||
z = sqlite3_malloc(nName + 4);
|
||||
if( z==0 ){
|
||||
rc = SQLITE_IOERR_NOMEM;
|
||||
}else{
|
||||
int iChunk = 0;
|
||||
int bExists;
|
||||
do{
|
||||
multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
|
||||
rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
|
||||
}while( rc==SQLITE_OK && bExists );
|
||||
while( rc==SQLITE_OK && iChunk>1 ){
|
||||
multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
|
||||
rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
|
||||
}
|
||||
}
|
||||
sqlite3_free(z);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
|
||||
@@ -662,7 +725,7 @@ static int multiplexRead(
|
||||
int rc = SQLITE_OK;
|
||||
multiplexEnter();
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen==0 ){
|
||||
rc = SQLITE_IOERR_READ;
|
||||
}else{
|
||||
@@ -671,7 +734,7 @@ static int multiplexRead(
|
||||
}else{
|
||||
while( iAmt > 0 ){
|
||||
int i = (int)(iOfst / pGroup->szChunk);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
|
||||
if( pSubOpen ){
|
||||
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
|
||||
if( extra<0 ) extra = 0;
|
||||
@@ -707,16 +770,16 @@ static int multiplexWrite(
|
||||
int rc = SQLITE_OK;
|
||||
multiplexEnter();
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen==0 ){
|
||||
rc = SQLITE_IOERR_WRITE;
|
||||
}else{
|
||||
rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
|
||||
}
|
||||
}else{
|
||||
while( iAmt > 0 ){
|
||||
while( rc==SQLITE_OK && iAmt>0 ){
|
||||
int i = (int)(iOfst / pGroup->szChunk);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
|
||||
if( pSubOpen ){
|
||||
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
|
||||
pGroup->szChunk;
|
||||
@@ -724,13 +787,9 @@ static int multiplexWrite(
|
||||
iAmt -= extra;
|
||||
rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
|
||||
iOfst % pGroup->szChunk);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
pBuf = (char *)pBuf + iAmt;
|
||||
iOfst += iAmt;
|
||||
iAmt = extra;
|
||||
}else{
|
||||
rc = SQLITE_IOERR_WRITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -748,28 +807,35 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
|
||||
int rc = SQLITE_OK;
|
||||
multiplexEnter();
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen==0 ){
|
||||
rc = SQLITE_IOERR_TRUNCATE;
|
||||
}else{
|
||||
rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
|
||||
}
|
||||
}else{
|
||||
int rc2;
|
||||
int i;
|
||||
int iBaseGroup = (int)(size / pGroup->szChunk);
|
||||
sqlite3_file *pSubOpen;
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||
/* delete the chunks above the truncate limit */
|
||||
for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){
|
||||
multiplexSubClose(pGroup, i, pOrigVfs);
|
||||
for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){
|
||||
if( pGroup->bTruncate ){
|
||||
multiplexSubClose(pGroup, i, pOrigVfs);
|
||||
}else{
|
||||
pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0);
|
||||
if( pSubOpen ){
|
||||
rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->szChunk), &rc2,0);
|
||||
if( pSubOpen ){
|
||||
rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
|
||||
if( rc2!=SQLITE_OK ) rc = rc2;
|
||||
}else{
|
||||
rc = SQLITE_IOERR_TRUNCATE;
|
||||
if( rc==SQLITE_OK ){
|
||||
pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0);
|
||||
if( pSubOpen ){
|
||||
rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
|
||||
}
|
||||
}
|
||||
if( rc ) rc = SQLITE_IOERR_TRUNCATE;
|
||||
}
|
||||
multiplexLeave();
|
||||
return rc;
|
||||
@@ -801,47 +867,21 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
multiplexGroup *pGroup = p->pGroup;
|
||||
int rc = SQLITE_OK;
|
||||
int rc2;
|
||||
int i;
|
||||
multiplexEnter();
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen==0 ){
|
||||
rc = SQLITE_IOERR_FSTAT;
|
||||
}else{
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
|
||||
}
|
||||
}else{
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
|
||||
*pSize = 0;
|
||||
for(i=0; 1; i++){
|
||||
sqlite3_file *pSubOpen = 0;
|
||||
int exists = 0;
|
||||
rc = multiplexSubFilename(pGroup, i);
|
||||
if( rc ) break;
|
||||
rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
|
||||
SQLITE_ACCESS_EXISTS, &exists);
|
||||
if( rc2==SQLITE_OK && exists){
|
||||
/* if it exists, open it */
|
||||
pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
|
||||
}else{
|
||||
/* stop at first "gap" */
|
||||
break;
|
||||
}
|
||||
if( pSubOpen ){
|
||||
sqlite3_int64 sz;
|
||||
rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
if( rc2!=SQLITE_OK ){
|
||||
rc = rc2;
|
||||
}else{
|
||||
if( sz>pGroup->szChunk ){
|
||||
rc = SQLITE_IOERR_FSTAT;
|
||||
}
|
||||
*pSize += sz;
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
for(i=0; rc==SQLITE_OK; i++){
|
||||
sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc);
|
||||
if( sz==0 ) break;
|
||||
*pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
|
||||
}
|
||||
}
|
||||
multiplexLeave();
|
||||
@@ -853,7 +893,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
|
||||
static int multiplexLock(sqlite3_file *pConn, int lock){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xLock(pSubOpen, lock);
|
||||
}
|
||||
@@ -865,7 +905,7 @@ static int multiplexLock(sqlite3_file *pConn, int lock){
|
||||
static int multiplexUnlock(sqlite3_file *pConn, int lock){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
|
||||
}
|
||||
@@ -877,7 +917,7 @@ static int multiplexUnlock(sqlite3_file *pConn, int lock){
|
||||
static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
|
||||
}
|
||||
@@ -925,9 +965,12 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
rc = SQLITE_OK;
|
||||
break;
|
||||
default:
|
||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
|
||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||
*(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -939,8 +982,8 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
static int multiplexSectorSize(sqlite3_file *pConn){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
if( pSubOpen ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
|
||||
return pSubOpen->pMethods->xSectorSize(pSubOpen);
|
||||
}
|
||||
return DEFAULT_SECTOR_SIZE;
|
||||
@@ -951,7 +994,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){
|
||||
static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
|
||||
}
|
||||
@@ -969,7 +1012,7 @@ static int multiplexShmMap(
|
||||
){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
|
||||
}
|
||||
@@ -986,7 +1029,7 @@ static int multiplexShmLock(
|
||||
){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
|
||||
}
|
||||
@@ -998,7 +1041,7 @@ static int multiplexShmLock(
|
||||
static void multiplexShmBarrier(sqlite3_file *pConn){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
pSubOpen->pMethods->xShmBarrier(pSubOpen);
|
||||
}
|
||||
@@ -1009,7 +1052,7 @@ static void multiplexShmBarrier(sqlite3_file *pConn){
|
||||
static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
int rc;
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen ){
|
||||
return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
|
||||
}
|
||||
@@ -1191,9 +1234,13 @@ static int test_multiplex_dump(
|
||||
for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){
|
||||
pGroupTerm = Tcl_NewObj();
|
||||
|
||||
pGroup->zName[pGroup->nName] = '\0';
|
||||
Tcl_ListObjAppendElement(interp, pGroupTerm,
|
||||
if( pGroup->zName ){
|
||||
pGroup->zName[pGroup->nName] = '\0';
|
||||
Tcl_ListObjAppendElement(interp, pGroupTerm,
|
||||
Tcl_NewStringObj(pGroup->zName, -1));
|
||||
}else{
|
||||
Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj());
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pGroupTerm,
|
||||
Tcl_NewIntObj(pGroup->nName));
|
||||
Tcl_ListObjAppendElement(interp, pGroupTerm,
|
||||
|
||||
+5
-1
@@ -389,7 +389,11 @@ static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
*/
|
||||
static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
VfslogFile *p = (VfslogFile *)pFile;
|
||||
return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
|
||||
int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
|
||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||
*(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+5
-1
@@ -589,7 +589,11 @@ static int quotaCheckReservedLock(sqlite3_file *pConn, int *pResOut){
|
||||
*/
|
||||
static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){
|
||||
sqlite3_file *pSubOpen = quotaSubOpen(pConn);
|
||||
return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
|
||||
int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
|
||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||
*(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Pass xSectorSize requests through to the original VFS unchanged.
|
||||
|
||||
+1
-1
@@ -369,7 +369,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
|
||||
|
||||
/* The default page size and offset */
|
||||
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
|
||||
pCsr->iOffset = pCsr->szPage * (pCsr->iPageno - 1);
|
||||
pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
|
||||
|
||||
/* If connected to a ZIPVFS backend, override the page size and
|
||||
** offset with actual values obtained from ZIPVFS.
|
||||
|
||||
@@ -471,6 +471,10 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
}
|
||||
case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break;
|
||||
case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break;
|
||||
case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break;
|
||||
case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break;
|
||||
case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break;
|
||||
case 0xca093fa0: zOp = "DB_UNCHANGED"; break;
|
||||
default: {
|
||||
sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
|
||||
@@ -482,6 +486,10 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
pInfo->zVfsName, p->zFName, zOp);
|
||||
rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||
*(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
|
||||
pInfo->zVfsName, *(char**)pArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,6 +1169,7 @@ int sqlite3AbsInt32(int x){
|
||||
** test.db-journal => test.nal
|
||||
** test.db-wal => test.wal
|
||||
** test.db-shm => test.shm
|
||||
** test.db-mj7f3319fa => test.9fa
|
||||
*/
|
||||
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
||||
#if SQLITE_ENABLE_8_3_NAMES<2
|
||||
|
||||
+15
-5
@@ -1824,16 +1824,26 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
sqlite3_file *pMaster = 0;
|
||||
i64 offset = 0;
|
||||
int res;
|
||||
int retryCount = 0;
|
||||
int nMainFile;
|
||||
|
||||
/* Select a master journal file name */
|
||||
nMainFile = sqlite3Strlen30(zMainFile);
|
||||
zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XX", zMainFile);
|
||||
if( zMaster==0 ) return SQLITE_NOMEM;
|
||||
do {
|
||||
u32 iRandom;
|
||||
sqlite3DbFree(db, zMaster);
|
||||
sqlite3_randomness(sizeof(iRandom), &iRandom);
|
||||
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
|
||||
if( !zMaster ){
|
||||
return SQLITE_NOMEM;
|
||||
if( retryCount++>100 ){
|
||||
sqlite3_log(SQLITE_FULL, "cannot find unique master-journal");
|
||||
sqlite3OsDelete(pVfs, zMaster, 0);
|
||||
break;
|
||||
}
|
||||
sqlite3_randomness(sizeof(iRandom), &iRandom);
|
||||
sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
|
||||
(iRandom>>8)&0xffffff, iRandom&0xff);
|
||||
/* The antipenultimate character of the master journal name must
|
||||
** be "9" to avoid name collisions when using 8+3 filenames. */
|
||||
assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
|
||||
sqlite3FileSuffix3(zMainFile, zMaster);
|
||||
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
||||
}while( rc==SQLITE_OK && res );
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# 2011 December 20
|
||||
#
|
||||
# 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 implements regression tests for SQLite library. The
|
||||
# focus of this script testing the ability of SQLite to handle database
|
||||
# files larger than 4GB.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bigfile2
|
||||
|
||||
# Create a small database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
|
||||
# Pad the file out to 4GB in size. Then clear the file-size field in the
|
||||
# db header. This will cause SQLite to assume that the first 4GB of pages
|
||||
# are actually in use and new pages will be appended to the file.
|
||||
#
|
||||
db close
|
||||
if {[catch {fake_big_file 4096 [pwd]/test.db} msg]} {
|
||||
puts "**** Unable to create a file larger than 4096 MB. *****"
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
hexio_write test.db 28 00000000
|
||||
|
||||
do_test 1.2 {
|
||||
file size test.db
|
||||
} [expr 14 + 4096 * (1<<20)]
|
||||
|
||||
# Now insert a large row. The overflow pages will be located past the 4GB
|
||||
# boundary. Then, after opening and closing the database, test that the row
|
||||
# can be read back in.
|
||||
#
|
||||
set str [string repeat k 30000]
|
||||
do_test 1.3 {
|
||||
sqlite3 db test.db
|
||||
execsql { INSERT INTO t1 VALUES(3, $str) }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
db one { SELECT b FROM t1 WHERE a = 3 }
|
||||
} $str
|
||||
|
||||
db close
|
||||
file delete test.db
|
||||
|
||||
finish_test
|
||||
+4
-4
@@ -573,10 +573,10 @@ set chunkconfig [fts3_configure_incr_load 1 1]
|
||||
foreach {tn create pending} {
|
||||
1 "fts4(a, b)" 1
|
||||
2 "fts4(a, b, order=ASC, prefix=1)" 1
|
||||
3 "fts4(a, b, order=ASC, prefix=1,3)" 0
|
||||
4 "fts4(a, b, order=DESC, prefix=2,4)" 0
|
||||
5 "fts4(a, b, order=DESC, prefix=1)" 0
|
||||
6 "fts4(a, b, order=ASC, prefix=1,3)" 0
|
||||
3 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0
|
||||
4 "fts4(a, b, order=DESC, prefix=\"2,4\")" 0
|
||||
5 "fts4(a, b, order=DESC, prefix=\"1\")" 0
|
||||
6 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0
|
||||
} {
|
||||
|
||||
execsql [subst {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# 2012 January 25
|
||||
#
|
||||
# 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 implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3prefix2
|
||||
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 { PRAGMA page_size = 512 }
|
||||
do_execsql_test 1.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(x, prefix="2,3");
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('T TX T TX T TX T TX T TX');
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 256
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 512
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 1024
|
||||
INSERT INTO t1 SELECT * FROM t1; -- 2048
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
|
||||
INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
|
||||
INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
|
||||
DELETE FROM t1 WHERE docid > 5;
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'T*';
|
||||
} {
|
||||
{T TX T TX T TX T TX T TX}
|
||||
{T TX T TX T TX T TX T TX}
|
||||
{T TX T TX T TX T TX T TX}
|
||||
{T TX T TX T TX T TX T TX}
|
||||
{T TX T TX T TX T TX T TX}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+21
-3
@@ -14,6 +14,16 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# The tests in this file assume that SQLite is compiled without
|
||||
# ENABLE_8_3_NAMES.
|
||||
#
|
||||
ifcapable 8_3_names {
|
||||
puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. "
|
||||
puts "Skipping tests multiplex-*."
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ]
|
||||
set g_max_chunks 32
|
||||
|
||||
@@ -24,7 +34,7 @@ set g_max_chunks 32
|
||||
# file name with the chunk number.
|
||||
proc multiplex_name {name chunk} {
|
||||
if {$chunk==0} { return $name }
|
||||
set num [format "%02d" $chunk]
|
||||
set num [format "%03d" $chunk]
|
||||
ifcapable {multiplex_ext_overwrite} {
|
||||
set name [string range $name 0 [expr [string length $name]-2-1]]
|
||||
}
|
||||
@@ -146,6 +156,9 @@ sqlite3_multiplex_initialize "" 1
|
||||
multiplex_set db main 32768 16
|
||||
|
||||
forcedelete test.x
|
||||
foreach f [glob -nocomplain {test.x*[0-9][0-9][0-9]}] {
|
||||
forcedelete $f
|
||||
}
|
||||
do_test multiplex-2.1.2 {
|
||||
sqlite3 db test.x
|
||||
execsql {
|
||||
@@ -182,12 +195,17 @@ do_test multiplex-2.4.2 {
|
||||
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
|
||||
} {}
|
||||
do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
|
||||
do_test multiplex-2.4.99 {
|
||||
do_test multiplex-2.4.5 {
|
||||
db close
|
||||
sqlite3 db test.x
|
||||
db eval vacuum
|
||||
db close
|
||||
glob test.x*
|
||||
} {test.x}
|
||||
do_test multiplex-2.4.99 {
|
||||
sqlite3_multiplex_shutdown
|
||||
} {SQLITE_OK}
|
||||
|
||||
|
||||
do_test multiplex-2.5.1 {
|
||||
multiplex_delete test.x
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# 2010 October 29
|
||||
#
|
||||
# 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/malloc_common.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
set testprefix multiplex2
|
||||
db close
|
||||
|
||||
do_multiclient_test tn {
|
||||
foreach f [glob -nocomplain test.*] { forcedelete $f }
|
||||
|
||||
code1 { catch { sqlite3_multiplex_initialize "" 0 } }
|
||||
code2 { catch { sqlite3_multiplex_initialize "" 0 } }
|
||||
|
||||
code1 { db close }
|
||||
code2 { db2 close }
|
||||
|
||||
code1 { sqlite3 db test.db -vfs multiplex }
|
||||
code2 { sqlite3 db2 test.db -vfs multiplex }
|
||||
|
||||
code1 { sqlite3_multiplex_control db main chunk_size [expr 1024*1024] }
|
||||
code2 { sqlite3_multiplex_control db2 main chunk_size [expr 1024*1024] }
|
||||
|
||||
sql1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(randomblob(10), randomblob(4000)); -- 1
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 256
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 512
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
do_test 1.$tn.1 { sql1 { SELECT count(*) FROM t1 } } 512
|
||||
do_test 1.$tn.2 { sql2 { SELECT count(*) FROM t1 } } 512
|
||||
sql2 { DELETE FROM t1 ; VACUUM }
|
||||
do_test 1.$tn.3 { sql1 { SELECT count(*) FROM t1 } } 0
|
||||
|
||||
sql1 {
|
||||
INSERT INTO t1 VALUES(randomblob(10), randomblob(4000)); -- 1
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 256
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 512
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
do_test 1.$tn.4 { sql2 { SELECT count(*) FROM t1 } } 512
|
||||
}
|
||||
|
||||
catch {db close}
|
||||
foreach f [glob -nocomplain test.*] { forcedelete $f }
|
||||
|
||||
ifcapable 8_3_names {
|
||||
sqlite3 db test.db -vfs multiplex
|
||||
sqlite3_multiplex_control db main chunk_size [expr 256*1024]
|
||||
|
||||
# Insert 512 * 256K (128MB) of data. If each row is around 4K, this means
|
||||
# we need 32768 rows.
|
||||
do_catchsql_test 2.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(randomblob(10), randomblob(4000)); -- 1
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 256
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 512
|
||||
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 1K
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 2K
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 4K
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 8K
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 16K
|
||||
INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1; -- 32K
|
||||
|
||||
} {1 {database or disk is full}}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
UPDATE t1 SET a=randomblob(9), b=randomblob(3900);
|
||||
PRAGMA integrity_check;
|
||||
} ok
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -vfs multiplex
|
||||
sqlite3_multiplex_control db main chunk_size [expr 256*1024]
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
PRAGMA integrity_check;
|
||||
} ok
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
catch { sqlite3_multiplex_shutdown }
|
||||
finish_test
|
||||
@@ -0,0 +1,133 @@
|
||||
|
||||
# 2011 December 13
|
||||
#
|
||||
# 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 error (IO, OOM etc.) handling when using
|
||||
# the multiplexor extension with 8.3 filenames.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
set ::testprefix multiplex3
|
||||
|
||||
ifcapable !8_3_names {
|
||||
puts -nonewline "SQLite compiled without SQLITE_ENABLE_8_3_NAMES. "
|
||||
puts "Skipping tests zipvfsD-*."
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
autoinstall_test_functions
|
||||
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
|
||||
proc destroy_vfs_stack {} {
|
||||
generic_unregister stack
|
||||
sqlite3_multiplex_shutdown
|
||||
}
|
||||
|
||||
proc multiplex_delete_db {} {
|
||||
forcedelete test.db
|
||||
for {set i 1} {$i <= 1000} {incr i} {
|
||||
forcedelete test.[format %03d $i]
|
||||
}
|
||||
}
|
||||
|
||||
# Procs to save and restore the current muliplexed database.
|
||||
#
|
||||
proc multiplex_save_db {} {
|
||||
foreach f [glob -nocomplain sv_test.*] { forcedelete $f }
|
||||
foreach f [glob -nocomplain test.*] { forcecopy $f "sv_$f" }
|
||||
}
|
||||
proc multiplex_restore_db {} {
|
||||
foreach f [glob -nocomplain test.*] {forcedelete $f}
|
||||
foreach f [glob -nocomplain sv_test.*] {forcecopy $f [string range $f 3 end]} }
|
||||
|
||||
proc setup_and_save_db {} {
|
||||
multiplex_delete_db
|
||||
sqlite3 db file:test.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 256*1024]
|
||||
execsql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(randomblob(15), randomblob(2000));
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 256
|
||||
INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 512
|
||||
}
|
||||
set ::cksum1 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
|
||||
db close
|
||||
multiplex_save_db
|
||||
}
|
||||
|
||||
do_test 1.0 { setup_and_save_db } {}
|
||||
do_faultsim_test 1 -prep {
|
||||
multiplex_restore_db
|
||||
sqlite3 db file:test.db?8_3_names=1
|
||||
sqlite3_multiplex_control db main chunk_size [expr 256*1024]
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
if {$testrc!=0} {
|
||||
set cksum2 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
|
||||
if {$cksum2 != $::cksum1} { error "data mismatch" }
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests verify that hot-journal rollback works. As follows:
|
||||
#
|
||||
# 1. Create a large database.
|
||||
# 2. Set the pager cache to be very small.
|
||||
# 3. Open a transaction.
|
||||
# 4. Run the following 100 times:
|
||||
# a. Update a row.
|
||||
# b. Copy all files on disk to a new db location, including the journal.
|
||||
# c. Verify that the new db can be opened and that the content matches
|
||||
# the database created in step 1 (proving the journal was rolled
|
||||
# back).
|
||||
|
||||
do_test 2.0 {
|
||||
setup_and_save_db
|
||||
multiplex_restore_db
|
||||
sqlite3 db file:test.db?8_3_names=1
|
||||
execsql { PRAGMA cache_size = 10 }
|
||||
execsql { BEGIN }
|
||||
} {}
|
||||
|
||||
for {set iTest 1} {$iTest<=100} {incr iTest} {
|
||||
do_test 2.$iTest {
|
||||
execsql {
|
||||
UPDATE t1 SET a=randomblob(12), b=randomblob(1400) WHERE rowid=5*$iTest
|
||||
}
|
||||
foreach f [glob -nocomplain test.*] {forcecopy $f "xx_$f"}
|
||||
sqlite3 db2 file:xx_test.db?8_3_names=1
|
||||
execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a} db2
|
||||
} $::cksum1
|
||||
|
||||
db2 close
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
sqlite3_multiplex_shutdown
|
||||
finish_test
|
||||
@@ -14,6 +14,8 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
unset -nocomplain defaultVfs
|
||||
set defaultVfs [file_control_vfsname db]
|
||||
db close
|
||||
|
||||
do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR}
|
||||
@@ -73,6 +75,9 @@ do_test quota-2.1.2 {
|
||||
}
|
||||
set ::quota
|
||||
} {}
|
||||
do_test quota-2.1.2.1 {
|
||||
file_control_vfsname db
|
||||
} quota/$defaultVfs
|
||||
do_test quota-2.1.3 { file size test.db } {4096}
|
||||
do_test quota-2.1.4 {
|
||||
catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
|
||||
|
||||
Reference in New Issue
Block a user