Compare commits

...

30 Commits

Author SHA1 Message Date
drh 76ea46c045 Fix the multiplexor logging so that it works with SQLITE_ENABLE_8_3_NAMES.
FossilOrigin-Name: 627eff32a23ec676f7e87f6904981b3804e0e1f0
2012-04-04 13:51:22 +00:00
drh 8e33b23089 In the multiplexor extension, improve the error logging when a chunk fails
to open.

FossilOrigin-Name: e6806f0dc6a06796700d805952f95e2cc18f0ea3
2012-04-04 13:47:35 +00:00
drh 1bfbdcbe6d Port the command-line shell enhancements including the new --cmd option
to the nx-devkit branch.

FossilOrigin-Name: 81ce52afb1bdb55d4585f01e7fb3ab86f81b7512
2012-02-07 14:22:18 +00:00
drh 03c8582307 Do not rely on the _WIN32_WINNT macro as vs2005 does not define it by default.
Instead, always assume winNT unless the makefile explicitly sets
SQLITE_OS_WINNT=0.

FossilOrigin-Name: 4f0997c7fab79cb7f12cf30f5ea5c87ce96bc266
2012-01-30 16:13:51 +00:00
drh e7cad43368 Cherrypick the FTS fix in [c05c3fd0d] into the nx-devkit branch.
Ticket [edb497982c].

FossilOrigin-Name: 2a7170f03c746473aca38ddc4b4a4091fe8331eb
2012-01-25 22:08:39 +00:00
drh 09a982e4ce Cherrypick the fix from [629108c8e5376f989] into the nx-devkit branch.
FossilOrigin-Name: d7374568cbce156523f5a6930e473ba2653c758b
2012-01-20 15:05:05 +00:00
drh 4a7eb4b545 Cherry-pick the fix to surplus overflow files in the multiplexor,
check-in [1238619756c0c] in the trunk.

FossilOrigin-Name: 2f8c62c3378a702fa623a2880a989d958eece0df
2012-01-09 14:57:38 +00:00
drh 34cf60ec74 Cherry-pick the SQLITE_DIRECT_OVERFLOW_READ fix for ticket
[ac0ff496b7e3] of changes [c5256b59ad] and [c723e3e18a] 
into the nx-devkit branch.

FossilOrigin-Name: 42f31f190a0ac971fa0ee361fe4c175f479c75e3
2011-12-21 23:38:21 +00:00
drh 8c24a369a5 Tweaks to the way multiplexSubOpen() works, for backwards compatibility.
FossilOrigin-Name: bb40338887c912be70cb6fe3b760d87c14bb88a5
2011-12-16 05:50:39 +00:00
drh 0699966798 Fix a potential infinite loop (inserted by the previous check-in)
on the multiplexWrite() method of the multiplexor.

FossilOrigin-Name: 022bf427c2edfe494ec7c222f436953ff56574a6
2011-12-16 05:09:46 +00:00
drh e7d9f13d99 The xTruncate method for the multiplexor now changes surplus overflow
files to zero-length by default.  Or if the "truncate" query parameter 
is used, it actually deletes the surplus overflow files.  This allows
VACUUM to shrink the database again.

FossilOrigin-Name: 5aefef04d6cc3b734c3f05e036b3869a52248f4d
2011-12-16 04:57:32 +00:00
drh 38deeb9763 Call sqlite3_log() with an appropriate message if unable to find a unique
master-journal filename.

FossilOrigin-Name: e9177f7d4ec19f0841d0613990d2fb5725700ba1
2011-12-16 01:30:15 +00:00
drh 5c531a4aab A better solution to being unable to find a unique master-journal filename:
just delete an existing master-journal and reuse it.

FossilOrigin-Name: 2685c2b949061f18bf6a4940eac8c8148873abb6
2011-12-16 01:21:31 +00:00
drh f580860f51 Make sure the antipenultimate character of master-journal filenames is a "9"
in order to avoid collisions with other files in 8+3 filename mode.  Also,
limit the number of attempts at finding a unique master-journal filename.

FossilOrigin-Name: 34a0483605d36e6cf03065ed0df33fb1f7c8a272
2011-12-16 00:33:04 +00:00
dan e712b5823e When deleting a file with the multiplexor VFS, also delete any overflow files that exist.
FossilOrigin-Name: 3af1feaa35d3fb2e7be550cd32a727001b874938
2011-12-15 17:00:10 +00:00
drh 78c0eafb35 Make sure the chunksize in test_multiplex does not cause the pending byte
to fall near the end of a chunk.  Adjust the chunksize upward as necessary
to prevent this.

FossilOrigin-Name: e05f8a2998f4f4cbdb65702baa65893c538b3d38
2011-12-15 13:29:12 +00:00
dan 31b21295b0 Fix some problems with dropped error codes in multiplexOpen().
FossilOrigin-Name: 2d50f78188e3297e8cefdf73cff51fa0a3b36e65
2011-12-15 11:45:19 +00:00
drh 2be25bffca In the multiplexor, do not try to delete overflow files that do not exist.
And assume all but the last overflow file is the size of the chunk size.

FossilOrigin-Name: a822a80d3cfe42b2fca6f8c9ff11762993114a27
2011-12-15 02:22:16 +00:00
drh 0f2ab8db33 Merge the VFSNAME file-control addition into the nx-devkit branch.
FossilOrigin-Name: 08c1dc517c1340737a55ad9012b7b06f72899c6f
2011-12-14 18:28:18 +00:00
drh de60fc2d87 Add a file-control that will discover the name of the bottom-level VFS and
all the shims in between.

FossilOrigin-Name: cdbfb553af02d10767a905489d9dfc57fc6be54e
2011-12-14 17:53:36 +00:00
drh 43a6d4bd44 Improvements to comments. No code changes.
FossilOrigin-Name: 08bbbd8e38697908ab8ae0f6b512d01c32f7e4da
2011-12-14 01:38:12 +00:00
dan 27e69643cf Add a hard limit to the number of chunks a multiplexed database may consist of if ENABLE_8_3_NAMES is defined.
FossilOrigin-Name: 43a1264088c57bf598787b7a9f5d7a2536603d67
2011-12-13 19:03:34 +00:00
drh c7f946297a Change the SQLITE_EXTRA_INIT routine to take a single argument which is a
pointer to a string.  Call SQLITE_EXTRA_INIT with a NULL argument.
Fixes to multiplexor to treat the VFS properly in corner cases.  Fix the
initialization of multiplex3.test.

FossilOrigin-Name: 8e65b9132530e46c62bd1352bfc2e9c29f57af5f
2011-12-13 18:22:38 +00:00
dan add995cc25 Add extra tests for the multiplexor VFS. No changes to code.
FossilOrigin-Name: c7de6f683d0fec62bc138b4a53b5cccc80c736c3
2011-12-13 16:40:33 +00:00
drh 658dd586ed Update the multiplex.test script to conform to that found in the "experimental"
branch off of trunk.

FossilOrigin-Name: 2eb79efbff9cdab843b172e9fa9fb400c542fab1
2011-12-13 15:25:06 +00:00
drh 5b1626aa47 Move the multiplexor changes in the experimental branch
(check-ins [255d21499b] and [199f52bced]) into the nx-devkit branch.

FossilOrigin-Name: eb95d2f72c625bcfd0f8e9db1db2cb8799854b57
2011-12-13 15:02:54 +00:00
drh e5077c1211 When an sqlite3_auto_extension() function fails, report back its actual
error code, not the generic SQLITE_ERROR.

FossilOrigin-Name: ce55f250f56fa3a1ca864f81e9e86f911b981490
2011-12-13 04:08:36 +00:00
drh 43795e3b0b When the multiplexor FileSize procedure fails to open the file, assume that
the file is zero bytes in size.

FossilOrigin-Name: dc8118cd89da71f2035c6ee07c0edb772bba2186
2011-12-13 02:41:13 +00:00
drh 9797706c04 Add a compile-time shutdown procedure to be called by sqlite3_shutdown()
to undo the effects of the compile-time initialization procedure.

FossilOrigin-Name: c2ed86f5945662a4ddcdc7b303df3f64fb3bf17d
2011-12-13 01:34:21 +00:00
drh 73795becfe Backport a minimal set of changes needed to get 8+3 filenames and the
multiplexor shim playing well together.

FossilOrigin-Name: c4e2ce486217c96373836bfe641f46abf891799a
2011-12-12 20:01:12 +00:00
30 changed files with 939 additions and 311 deletions
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+33 -29
View File
@@ -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
View File
@@ -1 +1 @@
1c45b2a0c055f6fc5da9d00ae2e9171099d904d4
627eff32a23ec676f7e87f6904981b3804e0e1f0
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+31
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+12
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+8
View File
@@ -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;
}
+1
View File
@@ -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
View File
@@ -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 );
+59
View File
@@ -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
View File
@@ -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 {
+62
View File
@@ -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
View File
@@ -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
+119
View File
@@ -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
+133
View File
@@ -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
+5
View File
@@ -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)) }