From d9523b97ecc218c2e8428eee636b6a5f557aef47 Mon Sep 17 00:00:00 2001 From: shaneh Date: Tue, 15 Mar 2011 04:45:48 +0000 Subject: [PATCH 01/31] Allow multiplex file names to be preceeded by prefix of the form ":multiplex:chunksize:maxchunks:" Still work to be done, though it compiles and prefixes are ignored. FossilOrigin-Name: cfa4a2f7ea948be0925227efca82baea509249c9 --- manifest | 15 +++++---- manifest.uuid | 2 +- src/test_multiplex.c | 75 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index a007a938e2..5ec64793db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scut-and-paste\stypo\sin\sdebugging\sprint\sstatement\sin\swinMutexTry(). -D 2011-03-15T02:55:28.657 +C Allow\smultiplex\sfile\snames\sto\sbe\spreceeded\sby\sprefix\sof\sthe\sform\s":multiplex:chunksize:maxchunks:"\s\nStill\swork\sto\sbe\sdone,\sthough\sit\scompiles\sand\sprefixes\sare\signored. +D 2011-03-15T04:45:48.735 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,7 +209,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c 655cb3b663f87db7d3d2427ea127c9daacae4abc +F src/test_multiplex.c cf01141845d29639de2b6cdd6d7ef9dc0bce2888 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c @@ -913,7 +913,10 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3934b004e93852c89b937ec20431de96a2e99440 -R a3bacb1f22d0b4cfa6cea5cf5efe9cdf +P def98fd23e42bda13547e38ab13fed0e6554ce99 +R 324244b8e2a2e32cd06c5dbee5aab290 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * U shaneh -Z 62a7f6dd55f1de5255b8d7f88e967001 +Z b5732ca362c3f4ec7a64142aa2707561 diff --git a/manifest.uuid b/manifest.uuid index 03da2a631d..ad05a9f286 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -def98fd23e42bda13547e38ab13fed0e6554ce99 \ No newline at end of file +cfa4a2f7ea948be0925227efca82baea509249c9 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 72a71621b4..694f7b4cb6 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -40,6 +40,8 @@ /************************ Shim Definitions ******************************/ +#define SQLITE_MULTIPLEX_VFS_NAME "multiplex" + /* This is the limit on the chunk size. It may be changed by calling ** the sqlite3_multiplex_set() interface. */ @@ -191,6 +193,53 @@ static sqlite3_file *multiplexSubOpen(multiplexConn *pConn, int iChunk, int *rc, return NULL; } +/* +** If the given filename begins with a valid multiplex prefix, return +** a pointer to the first character past the prefix. Otherwise +** return NULL pointer. If optional chunk size and max chunk +** values found, return them in int pointers. +*/ +static const char *multiplexParsePrefix(const char *zName, int *pChunkSize, int *pMaxChunks){ + int i; + int nChunkSize = 0; + int nMaxChunks = 0; + int lenPrefix = sqlite3Strlen30(SQLITE_MULTIPLEX_VFS_NAME)+2; + if( strncmp(zName, ":"SQLITE_MULTIPLEX_VFS_NAME":", lenPrefix)!=0 ) return 0; + /* if :multiplex: followed by ':' terminated string of digits, use + ** that value for the chunk size. */ + for(i=lenPrefix; sqlite3Isdigit(zName[i]); i++){ } + if ( zName[i]==':' ){ + if( pChunkSize ){ + if( sqlite3GetInt32(&zName[lenPrefix], &nChunkSize) ){ + *pChunkSize = nChunkSize; + } + } + lenPrefix = i+1; + /* if chunksize followed by ':' terminated string of digits, use + ** that value for the max chunks. */ + for(i=lenPrefix; sqlite3Isdigit(zName[i]); i++){ } + if ( zName[i]==':' ) { + if( pMaxChunks ){ + if( sqlite3GetInt32(&zName[lenPrefix], &nMaxChunks) ){ + *pMaxChunks = nMaxChunks; + } + } + lenPrefix = i+1; + } + } + return &zName[lenPrefix]; +} + +/* +** If the given filename that may or may not begin with a CEROD prefix, return +** a pointer to the first character of the filename past the prefix. +*/ +static const char *multiplexRootFilename(const char *zName){ + const char *zRoot = multiplexParsePrefix(zName, NULL, NULL); + if( zRoot==0 ) zRoot = zName; + return zRoot; +} + /************************* VFS Method Wrappers *****************************/ /* @@ -305,10 +354,10 @@ static int multiplexDelete( sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+nName, SQLITE_MULTIPLEX_EXT_FMT, i); #endif } - rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, multiplexRootFilename(gMultiplex.zName), SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, delete it */ - rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir); + rc2 = pOrigVfs->xDelete(pOrigVfs, multiplexRootFilename(gMultiplex.zName), syncDir); if( rc2!=SQLITE_OK ) rc = rc2; }else{ /* stop at first "gap" */ @@ -319,11 +368,19 @@ static int multiplexDelete( return rc; } -static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){ - return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d); +static int multiplexAccess(sqlite3_vfs *pVfs, const char *zName,int flgs,int *pOut){ + return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, multiplexRootFilename(zName), flgs, pOut); } -static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){ - return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d); +static int multiplexFullPathname(sqlite3_vfs *pVfs, const char *zName, int nOut, char *zOut){ + int n; + const char *zBase; + zBase = multiplexParsePrefix(zName, NULL, NULL); + if( zBase==0 ){ + return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, zName, nOut, zOut); + } + n = (int)(zBase - zName); + memcpy(zOut, zName, n); + return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, zBase, nOut - n, &zOut[n]); } static void *multiplexDlOpen(sqlite3_vfs *a, const char *b){ return gMultiplex.pOrigVfs->xDlOpen(gMultiplex.pOrigVfs, b); @@ -483,7 +540,7 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ #else sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); #endif - rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0); + rc2 = pOrigVfs->xDelete(pOrigVfs, multiplexRootFilename(gMultiplex.zName), 0); if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; } pSubOpen = multiplexSubOpen(p, (int)(size/gMultiplex.nChunkSize), &rc2, NULL); @@ -544,7 +601,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); #endif } - rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, multiplexRootFilename(gMultiplex.zName), SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, open it */ pSubOpen = multiplexSubOpen(p, i, &rc, NULL); @@ -738,7 +795,7 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ gMultiplex.pOrigVfs = pOrigVfs; gMultiplex.sThisVfs = *pOrigVfs; gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn); - gMultiplex.sThisVfs.zName = "multiplex"; + gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME; gMultiplex.sThisVfs.xOpen = multiplexOpen; gMultiplex.sThisVfs.xDelete = multiplexDelete; gMultiplex.sThisVfs.xAccess = multiplexAccess; From 326a67d0e8da09067c46001edb6808ba5fc3b02c Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Mar 2011 15:05:27 +0000 Subject: [PATCH 02/31] Skeleton code for the word-fuzzer virtual table. FossilOrigin-Name: ea3a4ee136ff6699c3099178f0efaa8bb517715f --- Makefile.in | 1 + main.mk | 1 + manifest | 34 +++- manifest.uuid | 2 +- src/tclsqlite.c | 2 + src/test_fuzzer.c | 407 ++++++++++++++++++++++++++++++++++++++++++++++ test/fuzzer1.test | 41 +++++ 7 files changed, 478 insertions(+), 10 deletions(-) create mode 100644 src/test_fuzzer.c create mode 100644 test/fuzzer1.test diff --git a/Makefile.in b/Makefile.in index 2c5490265d..2ee36dec43 100644 --- a/Makefile.in +++ b/Makefile.in @@ -356,6 +356,7 @@ TESTSRC = \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ + $(TOP)/src/test_fuzzer.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ diff --git a/main.mk b/main.mk index 29374c546f..cfea9b590f 100644 --- a/main.mk +++ b/main.mk @@ -237,6 +237,7 @@ TESTSRC = \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ + $(TOP)/src/test_fuzzer.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ diff --git a/manifest b/manifest index d485703eda..44205160e6 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,10 @@ -C Minor\schange\sto\ssqlite3Utf8Read()\sto\smake\sconsistent\swith\sREAD_UTF8()\susage\sand\savoid\simplementation\sdefined\susages\sof\s<<.\s\s\nAdded\ssome\sadditional\sUTF-8\stest\scases. -D 2011-03-24T17:43:18.990 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Skeleton\scode\sfor\sthe\sword-fuzzer\svirtual\stable. +D 2011-03-26T15:05:27.457 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f +F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 @@ -101,7 +104,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 54190fab7cdba523e311c274c95ea480f32abfb5 +F main.mk a767e12162f02719fa94697a6ff0c8b51bcd62a6 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -184,7 +187,7 @@ F src/sqliteInt.h f8f1d00a22c98fd3f2fbc94da74eeb880879f89f F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 879bf8a23d99fc0e99d9177fe1b48896bc796d65 +F src/tclsqlite.c 44979405594d33c55ec5ef8e82533d3b4133e455 F src/test1.c 9020310c7617234b33fd1c3064f89524db25f290 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -202,6 +205,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 +F src/test_fuzzer.c b09d2f47bc3ae1485100b323479c5d785d4f6e4b F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -475,6 +479,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c +F test/fuzzer1.test 29120e10821e2d04887b39c6c1ae4ddcbd2bb7f6 F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d @@ -916,7 +921,18 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 69fe0c873d702ef1d781453ee6ac2b1fb77fce48 -R 3655844fccb71eb3fdafa07a1f475145 -U shaneh -Z 4c379d73c236b4115e9dab5017415240 +P 7173b3929fae4e678223b0e978a2da7fa50a9005 +R 88772465d0029c6e2564e31a16d9e60f +T *bgcolor * #b0b28e +T *branch * word-fuzzer +T *sym-word-fuzzer * +T -sym-trunk * +U drh +Z 56aa191286824371992372fc6a5d252f +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFNjgC7oxKgR168RlERAutAAJ0V6j75yMfG5zTEYnDlvPG7yBJM5ACfSqKu +yFIOeN9GMM2kCskHQ5jGilY= +=IVMz +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 44925bdb50..a0f61071e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7173b3929fae4e678223b0e978a2da7fa50a9005 \ No newline at end of file +ea3a4ee136ff6699c3099178f0efaa8bb517715f \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 57f38d78d1..e77a1ee919 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3581,6 +3581,7 @@ static void init_all(Tcl_Interp *interp){ extern int Sqlitequota_Init(Tcl_Interp*); extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); + extern int Sqlitetestfuzzer_Init(Tcl_Interp*); #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); @@ -3618,6 +3619,7 @@ static void init_all(Tcl_Interp *interp){ Sqlitequota_Init(interp); Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); + Sqlitetestfuzzer_Init(interp); Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0); diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c new file mode 100644 index 0000000000..406c1a264e --- /dev/null +++ b/src/test_fuzzer.c @@ -0,0 +1,407 @@ +/* +** 2011 March 24 +** +** 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. +** +************************************************************************* +** +** Code for demonstartion virtual table that generates variations +** on an input word at increasing edit distances from the original. +*/ +#include "sqlite3.h" +#include +#include +#include + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* +** Forward declaration of objects used by this implementation +*/ +typedef struct fuzzer_vtab fuzzer_vtab; +typedef struct fuzzer_cursor fuzzer_cursor; +typedef struct fuzzer_rule fuzzer_rule; +typedef struct fuzzer_seen fuzzer_seen; +typedef struct fuzzer_stem fuzzer_stem; + + +/* +** Each transformation rule is stored as an instance of this object. +** All rules are kept on a linked list sorted by rCost. +*/ +struct fuzzer_rule { + fuzzer_rule *pNext; /* Next rule in order of increasing rCost */ + float rCost; /* Cost of this transformation */ + char *zFrom; /* Transform from */ + char zTo[4]; /* Transform to (extra space appended) */ +}; + +/* +** When generating fuzzed words, we have to remember all previously +** generated terms in order to suppress duplicates. Each previously +** generated term is an instance of the following structure. +*/ +struct fuzzer_seen { + fuzzer_seen *pNext; /* Next with the same hash */ + char zWord[4]; /* The generated term. */ +}; + +/* +** A stem object is used to generate variants. +*/ +struct fuzzer_stem { + char *zBasis; /* Word being fuzzed */ + fuzzer_rule *pRule; /* Next rule to apply */ + int n; /* Apply rule at this character offset */ + float rBaseCost; /* Base cost of getting to zBasis */ + float rCost; /* rBaseCost + cost of applying pRule at n */ + fuzzer_stem *pNext; /* Next stem in rCost order */ +}; + +/* +** A fuzzer virtual-table object +*/ +struct fuzzer_vtab { + sqlite3_vtab base; /* Base class - must be first */ + char *zClassName; /* Name of this class. Default: "fuzzer" */ + fuzzer_rule *pRule; /* All active rules in this fuzzer */ + fuzzer_rule *pNewRule; /* New rules to add when last cursor expires */ + int nCursor; /* Number of active cursors */ +}; + +/* A fuzzer cursor object */ +struct fuzzer_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + float rMax; /* Maximum cost of any term */ + fuzzer_stem *pStem; /* Sorted list of stems for generating new terms */ + int nSeen; /* Number of terms already generated */ + int nHash; /* Number of slots in apHash */ + fuzzer_seen **apHash; /* Hash table of previously generated terms */ +}; + +/* Methods for the fuzzer module */ +static int fuzzerConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + fuzzer_vtab *pNew; + char *zSql; + int n; + if( strcmp(argv[1],"temp")!=0 ){ + *pzErr = sqlite3_mprintf("%s virtual tables must be TEMP", argv[0]); + return SQLITE_ERROR; + } + n = strlen(argv[0]) + 1; + pNew = sqlite3_malloc( sizeof(*pNew) + n ); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->zClassName = (char*)&pNew[1]; + memcpy(pNew->zClassName, argv[0], n); + zSql = sqlite3_mprintf( + "CREATE TABLE x(word, distance, cFrom, cTo, cost, \"%w\" HIDDEN)", + argv[2] + ); + sqlite3_declare_vtab(db, zSql); + sqlite3_free(zSql); + memset(pNew, 0, sizeof(*pNew)); + *ppVtab = &pNew->base; + return SQLITE_OK; +} +/* Note that for this virtual table, the xCreate and xConnect +** methods are identical. */ + +static int fuzzerDisconnect(sqlite3_vtab *pVtab){ + fuzzer_vtab *p = (fuzzer_vtab*)pVtab; + assert( p->nCursor==0 ); + do{ + while( p->pRule ){ + fuzzer_rule *pRule = p->pRule; + p->pRule = pRule->pNext; + sqlite3_free(pRule); + } + p->pRule = p->pNewRule; + p->pNewRule = 0; + }while( p->pRule ); + sqlite3_free(p); + return SQLITE_OK; +} +/* The xDisconnect and xDestroy methods are also the same */ + +/* +** The two input rule lists are both sorted in order of increasing +** cost. Merge them together into a single list, sorted by cost, and +** return a pointer to the head of that list. +*/ +static fuzzer_rule *fuzzerMergeRules(fuzzer_rule *pA, fuzzer_rule *pB){ + fuzzer_rule head; + fuzzer_rule *pTail; + + pTail = &head; + while( pA && pB ){ + if( pA->rCost<=pB->rCost ){ + pTail->pNext = pA; + pTail = pA; + pA = pA->pNext; + }else{ + pTail->pNext = pB; + pTail = pB; + pB = pB->pNext; + } + } + if( pA==0 ){ + pTail->pNext = pB; + }else{ + pTail->pNext = pA; + } + return head.pNext; +} + + +/* +** Open a new fuzzer cursor. +*/ +static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + fuzzer_vtab *p = (fuzzer_vtab*)pVTab; + fuzzer_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + if( p->nCursor==0 && p->pNewRule ){ + unsigned int i; + fuzzer_rule *pX; + fuzzer_rule *a[15]; + for(i=0; ipNewRule)!=0 ){ + p->pNewRule = pX->pNext; + pX->pNext = 0; + for(i=0; a[i] && ipRule = fuzzerMergeRules(p->pRule, pX); + } + + return SQLITE_OK; +} + +/* +** Close a fuzzer cursor. +*/ +static int fuzzerClose(sqlite3_vtab_cursor *cur){ + fuzzer_cursor *pCur = (fuzzer_cursor *)cur; + int i; + for(i=0; inHash; i++){ + fuzzer_seen *pSeen = pCur->apHash[i]; + while( pSeen ){ + fuzzer_seen *pNext = pSeen->pNext; + sqlite3_free(pSeen); + pSeen = pNext; + } + } + sqlite3_free(pCur->apHash); + while( pCur->pStem ){ + fuzzer_stem *pStem = pCur->pStem; + pCur->pStem = pStem->pNext; + sqlite3_free(pStem); + } + sqlite3_free(pCur); + return SQLITE_OK; +} + +static int fuzzerNext(sqlite3_vtab_cursor *cur){ + return 0; +} + +static int fuzzerFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor; + return fuzzerNext(pVtabCursor); +} + +static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + fuzzer_cursor *pCur = (fuzzer_cursor*)cur; + return SQLITE_OK; +} + +static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + *pRowid = 0; + return SQLITE_OK; +} + +static int fuzzerEof(sqlite3_vtab_cursor *cur){ + fuzzer_cursor *pCur = (fuzzer_cursor*)cur; + return 1; +} + +static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + + return SQLITE_OK; +} + +/* +** Disallow all attempts to DELETE or UPDATE. Only INSERTs are allowed. +** +** On an insert, the cFrom, cTo, and cost columns are used to construct +** a new rule. All other columns are ignored. The rule is ignored +** if cFrom and cTo are identical. A NULL value for cFrom or cTo is +** interpreted as an empty string. The cost must be positive. +*/ +static int fuzzerUpdate( + sqlite3_vtab *pVTab, + int argc, + sqlite3_value **argv, + sqlite_int64 *pRowid +){ + fuzzer_vtab *p = (fuzzer_vtab*)pVTab; + fuzzer_rule *pRule; + const char *zFrom; + int nFrom; + const char *zTo; + int nTo; + float rCost; + if( argc!=8 ){ + sqlite3_free(pVTab->zErrMsg); + pVTab->zErrMsg = sqlite3_mprintf("cannot delete from a %s virtual table", + p->zClassName); + return SQLITE_CONSTRAINT; + } + if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){ + sqlite3_free(pVTab->zErrMsg); + pVTab->zErrMsg = sqlite3_mprintf("cannot update a %s virtual table", + p->zClassName); + return SQLITE_CONSTRAINT; + } + zFrom = (char*)sqlite3_value_text(argv[4]); + if( zFrom==0 ) zFrom = ""; + zTo = (char*)sqlite3_value_text(argv[5]); + if( zTo==0 ) zTo = ""; + if( strcmp(zFrom,zTo)==0 ){ + /* Silently ignore null transformations */ + return SQLITE_OK; + } + rCost = (float)sqlite3_value_double(argv[6]); + if( rCost<=0 ){ + sqlite3_free(pVTab->zErrMsg); + pVTab->zErrMsg = sqlite3_mprintf("cost must be positive"); + return SQLITE_CONSTRAINT; + } + nFrom = strlen(zFrom)+1; + nTo = strlen(zTo)+1; + if( nTo<4 ) nTo = 4; + pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo - 4 ); + if( pRule==0 ){ + return SQLITE_NOMEM; + } + pRule->zFrom = &pRule->zTo[nTo]; + memcpy(pRule->zFrom, zFrom, nFrom); + memcpy(pRule->zTo, zTo, nTo); + pRule->rCost = rCost; + pRule->pNext = p->pNewRule; + p->pNewRule = pRule; + return SQLITE_OK; +} + +/* +** A virtual table module that provides read-only access to a +** Tcl global variable namespace. +*/ +static sqlite3_module fuzzerModule = { + 0, /* iVersion */ + fuzzerConnect, + fuzzerConnect, + fuzzerBestIndex, + fuzzerDisconnect, + fuzzerDisconnect, + fuzzerOpen, /* xOpen - open a cursor */ + fuzzerClose, /* xClose - close a cursor */ + fuzzerFilter, /* xFilter - configure scan constraints */ + fuzzerNext, /* xNext - advance a cursor */ + fuzzerEof, /* xEof - check for end of scan */ + fuzzerColumn, /* xColumn - read data */ + fuzzerRowid, /* xRowid - read data */ + fuzzerUpdate, /* xUpdate - INSERT */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + +/* +** Register the fuzzer virtual table +*/ +int fuzzer_register(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0); +#endif + return rc; +} + +#ifdef SQLITE_TEST +#include +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the echo virtual table module. +*/ +static int register_fuzzer_module( + 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; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + fuzzer_register(db); + return TCL_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetestfuzzer_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "register_fuzzer_module", register_fuzzer_module, 0 }, + }; + int i; + for(i=0; i Date: Sat, 26 Mar 2011 19:04:47 +0000 Subject: [PATCH 03/31] Added most of the logic. Simple test runs without segfaulting but does not give the correct answer. FossilOrigin-Name: fb4c31eac8a7290f61c50a3552245660e1271871 --- manifest | 24 ++- manifest.uuid | 2 +- src/test_fuzzer.c | 380 +++++++++++++++++++++++++++++++++++++++------- test/fuzzer1.test | 12 +- 4 files changed, 344 insertions(+), 74 deletions(-) diff --git a/manifest b/manifest index 44205160e6..a9cd7caec3 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Skeleton\scode\sfor\sthe\sword-fuzzer\svirtual\stable. -D 2011-03-26T15:05:27.457 +C Added\smost\sof\sthe\slogic.\s\sSimple\stest\sruns\swithout\ssegfaulting\sbut\sdoes\snot\ngive\sthe\scorrect\sanswer. +D 2011-03-26T19:04:47.346 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -205,7 +205,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c b09d2f47bc3ae1485100b323479c5d785d4f6e4b +F src/test_fuzzer.c 133c830fdd4342b687910a04cf8e617e0f5f0e5f F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -479,7 +479,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/fuzzer1.test 29120e10821e2d04887b39c6c1ae4ddcbd2bb7f6 +F test/fuzzer1.test e0fe96bb8d318250b35407954c7059eea8ea77b2 F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d @@ -921,18 +921,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 7173b3929fae4e678223b0e978a2da7fa50a9005 -R 88772465d0029c6e2564e31a16d9e60f -T *bgcolor * #b0b28e -T *branch * word-fuzzer -T *sym-word-fuzzer * -T -sym-trunk * +P ea3a4ee136ff6699c3099178f0efaa8bb517715f +R 6a09f2dbc53bf6a269c56104914ae3e5 U drh -Z 56aa191286824371992372fc6a5d252f +Z c40c33ca74d9ed106c795140b6ad71ee -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFNjgC7oxKgR168RlERAutAAJ0V6j75yMfG5zTEYnDlvPG7yBJM5ACfSqKu -yFIOeN9GMM2kCskHQ5jGilY= -=IVMz +iD8DBQFNjjjSoxKgR168RlERAjfMAKCJigUMIbnNV83nhVCWCpDK5WxPFQCeLIbS ++J80DLXre8S3k4SR8glB8Jc= +=nBDg -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index a0f61071e0..54187bc30b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea3a4ee136ff6699c3099178f0efaa8bb517715f \ No newline at end of file +fb4c31eac8a7290f61c50a3552245660e1271871 \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index 406c1a264e..e4aca40fc8 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -29,38 +29,36 @@ typedef struct fuzzer_rule fuzzer_rule; typedef struct fuzzer_seen fuzzer_seen; typedef struct fuzzer_stem fuzzer_stem; +/* +** Type of the "cost" of an edit operation. Might be changed to +** "float" or "double" or "sqlite3_int64" in the future. +*/ +typedef int fuzzer_cost; + /* ** Each transformation rule is stored as an instance of this object. ** All rules are kept on a linked list sorted by rCost. */ struct fuzzer_rule { - fuzzer_rule *pNext; /* Next rule in order of increasing rCost */ - float rCost; /* Cost of this transformation */ - char *zFrom; /* Transform from */ - char zTo[4]; /* Transform to (extra space appended) */ -}; - -/* -** When generating fuzzed words, we have to remember all previously -** generated terms in order to suppress duplicates. Each previously -** generated term is an instance of the following structure. -*/ -struct fuzzer_seen { - fuzzer_seen *pNext; /* Next with the same hash */ - char zWord[4]; /* The generated term. */ + fuzzer_rule *pNext; /* Next rule in order of increasing rCost */ + fuzzer_cost rCost; /* Cost of this transformation */ + int nFrom, nTo; /* Length of the zFrom and zTo strings */ + char *zFrom; /* Transform from */ + char zTo[4]; /* Transform to (extra space appended) */ }; /* ** A stem object is used to generate variants. */ struct fuzzer_stem { - char *zBasis; /* Word being fuzzed */ - fuzzer_rule *pRule; /* Next rule to apply */ - int n; /* Apply rule at this character offset */ - float rBaseCost; /* Base cost of getting to zBasis */ - float rCost; /* rBaseCost + cost of applying pRule at n */ - fuzzer_stem *pNext; /* Next stem in rCost order */ + char *zBasis; /* Word being fuzzed */ + int nBasis; /* Length of the zBasis string */ + const fuzzer_rule *pRule; /* Current rule to apply */ + int n; /* Apply pRule at this character offset */ + fuzzer_cost rBaseCost; /* Base cost of getting to zBasis */ + fuzzer_stem *pNext; /* Next stem in rCost order */ + fuzzer_stem *pHash; /* Next stem with same hash on zBasis */ }; /* @@ -74,14 +72,18 @@ struct fuzzer_vtab { int nCursor; /* Number of active cursors */ }; +#define FUZZER_HASH 4001 /* Hash table size */ + /* A fuzzer cursor object */ struct fuzzer_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ - float rMax; /* Maximum cost of any term */ + fuzzer_vtab *pVtab; /* The virtual table this cursor belongs to */ + fuzzer_cost rLimit; /* Maximum cost of any term */ fuzzer_stem *pStem; /* Sorted list of stems for generating new terms */ - int nSeen; /* Number of terms already generated */ - int nHash; /* Number of slots in apHash */ - fuzzer_seen **apHash; /* Hash table of previously generated terms */ + fuzzer_stem *pDone; /* Stems already processed to completion */ + char *zBuf; /* Temporary use buffer */ + int nBuf; /* Bytes allocated for zBuf */ + fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */ }; /* Methods for the fuzzer module */ @@ -93,7 +95,6 @@ static int fuzzerConnect( char **pzErr ){ fuzzer_vtab *pNew; - char *zSql; int n; if( strcmp(argv[1],"temp")!=0 ){ *pzErr = sqlite3_mprintf("%s virtual tables must be TEMP", argv[0]); @@ -104,12 +105,7 @@ static int fuzzerConnect( if( pNew==0 ) return SQLITE_NOMEM; pNew->zClassName = (char*)&pNew[1]; memcpy(pNew->zClassName, argv[0], n); - zSql = sqlite3_mprintf( - "CREATE TABLE x(word, distance, cFrom, cTo, cost, \"%w\" HIDDEN)", - argv[2] - ); - sqlite3_declare_vtab(db, zSql); - sqlite3_free(zSql); + sqlite3_declare_vtab(db, "CREATE TABLE x(word,distance,cFrom,cTo,cost)"); memset(pNew, 0, sizeof(*pNew)); *ppVtab = &pNew->base; return SQLITE_OK; @@ -173,7 +169,9 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); + pCur->pVtab = p; *ppCursor = &pCur->base; + p->nCursor++; if( p->nCursor==0 && p->pNewRule ){ unsigned int i; fuzzer_rule *pX; @@ -193,64 +191,332 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ } p->pRule = fuzzerMergeRules(p->pRule, pX); } - return SQLITE_OK; } +/* +** Free up all the memory allocated by a cursor. Set it rLimit to 0 +** to indicate that it is at EOF. +*/ +static void fuzzerClearCursor(fuzzer_cursor *pCur, int clearHash){ + if( pCur->pStem==0 && pCur->pDone==0 ) clearHash = 0; + do{ + while( pCur->pStem ){ + fuzzer_stem *pStem = pCur->pStem; + pCur->pStem = pStem->pNext; + sqlite3_free(pStem); + } + pCur->pStem = pCur->pDone; + pCur->pDone = 0; + }while( pCur->pStem ); + pCur->rLimit = (fuzzer_cost)0; + if( clearHash ) memset(pCur->apHash, 0, sizeof(pCur->apHash)); +} + /* ** Close a fuzzer cursor. */ static int fuzzerClose(sqlite3_vtab_cursor *cur){ fuzzer_cursor *pCur = (fuzzer_cursor *)cur; - int i; - for(i=0; inHash; i++){ - fuzzer_seen *pSeen = pCur->apHash[i]; - while( pSeen ){ - fuzzer_seen *pNext = pSeen->pNext; - sqlite3_free(pSeen); - pSeen = pNext; - } - } - sqlite3_free(pCur->apHash); - while( pCur->pStem ){ - fuzzer_stem *pStem = pCur->pStem; - pCur->pStem = pStem->pNext; - sqlite3_free(pStem); - } - sqlite3_free(pCur); + fuzzerClearCursor(pCur, 0); + sqlite3_free(pCur->zBuf); + pCur->pVtab->nCursor--; return SQLITE_OK; } -static int fuzzerNext(sqlite3_vtab_cursor *cur){ +/* +** Compute the current output term for a fuzzer_stem. +*/ +static int fuzzerComputeWord( + fuzzer_cursor *pCur, + fuzzer_stem *pStem +){ + const fuzzer_rule *pRule = pStem->pRule; + int n; + + n = pStem->nBasis; + if( pStem->n>=0 ) n += pRule->nTo - pRule->nFrom; + if( pCur->nBufzBuf = sqlite3_realloc(pCur->zBuf, n+100); + if( pCur->zBuf==0 ) return SQLITE_NOMEM; + pCur->nBuf = n+100; + } + n = pStem->n; + if( n<0 ){ + memcpy(pCur->zBuf, pStem->zBasis, pStem->nBasis+1); + }else{ + memcpy(pCur->zBuf, pStem->zBasis, n); + memcpy(&pCur->zBuf[n], pRule->zTo, pRule->nTo); + memcpy(&pCur->zBuf[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], + pStem->nBasis-n-pRule->nFrom+1); + } + return SQLITE_OK; +} + + +/* +** Compute a hash on zBasis. +*/ +static unsigned int fuzzerHash(const char *z){ + unsigned int h = 0; + while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); } + return h%10007; +} + +/* +** Current cost of a stem +*/ +static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){ + return pStem->rBaseCost + pStem->pRule->rCost; +} + +/* +** Advance a fuzzer_stem to its next value. Return 0 if there are +** no more values that can be generated by this fuzzer_stem. +*/ +static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ + const fuzzer_rule *pRule; + while( (pRule = pStem->pRule)!=0 ){ + while( pStem->n < pStem->nBasis - pRule->nFrom ){ + pStem->n++; + if( pRule->nFrom==0 + || memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0 + ){ + /* Found a rewrite case. Make sure it is not a duplicate */ + unsigned int h; + fuzzer_stem *pLookup; + + fuzzerComputeWord(pCur, pStem); + h = fuzzerHash(pCur->zBuf); + pLookup = pCur->apHash[h]; + while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){ + pLookup = pLookup->pHash; + } + if( pLookup==0 ) return 1; /* A new output is found. */ + } + } + pStem->n = -1; + pStem->pRule = pRule->pNext; + if( fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0; + } return 0; } +/* +** Insert pNew into the list at pList. Return a pointer to the new +** list. The insert is done such the pNew is in the correct order +** according to fuzzer_stem.zBaseCost+fuzzer_stem.pRule->rCost. +*/ +static fuzzer_stem *fuzzerInsert(fuzzer_stem *pList, fuzzer_stem *pNew){ + fuzzer_cost c1; + + c1 = fuzzerCost(pNew); + if( c1 <= fuzzerCost(pList) ){ + pNew->pNext = pList; + return pNew; + }else{ + fuzzer_stem *pPrev; + pPrev = pList; + while( pPrev->pNext && fuzzerCost(pPrev->pNext)pNext; + } + pNew->pNext = pPrev->pNext; + pPrev->pNext = pNew; + return pList; + } +} + +/* +** Allocate a new fuzzer_stem. Add it to the hash table but do not +** link it into either the pCur->pStem or pCur->pDone lists. +*/ +static fuzzer_stem *fuzzerNewStem( + fuzzer_cursor *pCur, + const char *zWord, + fuzzer_cost rBaseCost +){ + fuzzer_stem *pNew; + unsigned int h; + + pNew = sqlite3_malloc( sizeof(*pNew) + strlen(zWord) + 1 ); + if( pNew==0 ) return 0; + memset(pNew, 0, sizeof(*pNew)); + pNew->zBasis = (char*)&pNew[1]; + pNew->nBasis = strlen(zWord); + memcpy(pNew->zBasis, zWord, pNew->nBasis+1); + pNew->pRule = pCur->pVtab->pRule; + pNew->n = -1; + pNew->rBaseCost = rBaseCost; + h = fuzzerHash(pNew->zBasis); + pNew->pHash = pCur->apHash[h]; + pCur->apHash[h] = pNew; + return pNew; +} + + +/* +** Advance a cursor to its next row of output +*/ +static int fuzzerNext(sqlite3_vtab_cursor *cur){ + fuzzer_cursor *pCur = (fuzzer_cursor*)pCur; + fuzzer_stem *pStem, *pNew; + + /* Use the element the cursor is currently point to to create + ** a new stem and insert the new stem into the priority queue. + */ + fuzzerComputeWord(pCur, pCur->pStem); + pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pCur->pStem)); + if( pNew ){ + if( fuzzerAdvance(pCur, pNew)==0 ){ + pNew->pNext = pCur->pDone; + pCur->pDone = pNew; + }else{ + pCur->pStem = fuzzerInsert(pCur->pStem, pNew); + } + } + + /* Adjust the priority queue so that the first element of the + ** stem list is the next lowest cost word. + */ + while( (pStem = pCur->pStem)!=0 ){ + if( fuzzerAdvance(pCur, pStem) ){ + pCur->pStem = fuzzerInsert(pStem->pNext, pStem); + return SQLITE_OK; /* New word found */ + } + pCur->pStem = pStem->pNext; + pStem->pNext = pCur->pDone; + pCur->pDone = pStem; + } + + /* Reach this point only if queue has been exhausted and there is + ** nothing left to be output. */ + pCur->rLimit = (fuzzer_cost)0; + return SQLITE_OK; +} + +/* +** Called to "rewind" a cursor back to the beginning so that +** it starts its output over again. Always called at least once +** prior to any fuzzerColumn, fuzzerRowid, or fuzzerEof call. +*/ static int fuzzerFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor; - return fuzzerNext(pVtabCursor); + const char *zWord = 0; + pCur->rLimit = 2147483647; + + fuzzerClearCursor(pCur, 1); + if( idxNum==1 ){ + zWord = (const char*)sqlite3_value_text(argv[0]); + }else if( idxNum==2 ){ + pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[0]); + }else if( idxNum==3 ){ + zWord = (const char*)sqlite3_value_text(argv[0]); + pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[1]); + } + if( zWord==0 ) zWord = ""; + pCur->pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0); + if( pCur->pStem==0 ) return SQLITE_NOMEM; + return SQLITE_OK; } +/* +** Only the word and distance columns have values. All other columns +** return NULL +*/ static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ fuzzer_cursor *pCur = (fuzzer_cursor*)cur; + if( i==0 ){ + /* the "word" column */ + if( fuzzerComputeWord(pCur, pCur->pStem)==SQLITE_NOMEM ){ + return SQLITE_NOMEM; + } + sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); + }else if( i==1 ){ + /* the "distance" column */ + sqlite3_result_int(ctx, fuzzerCost(pCur->pStem)); + }else{ + /* All other columns are NULL */ + sqlite3_result_null(ctx); + } return SQLITE_OK; } +/* +** The rowid is always 0 +*/ static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - *pRowid = 0; + *pRowid = 0; /* The rowid is always 0 */ return SQLITE_OK; } +/* +** When the fuzzer_cursor.rLimit value is 0 or less, that is a signal +** that the cursor has nothing more to output. +*/ static int fuzzerEof(sqlite3_vtab_cursor *cur){ fuzzer_cursor *pCur = (fuzzer_cursor*)cur; - return 1; + return pCur->rLimit<=(fuzzer_cost)0; } +/* +** Search for terms of these forms: +** +** word MATCH $str +** distance < $value +** distance <= $value +** +** The distance< and distance<= are both treated as distance<=. +** The query plan number is as follows: +** +** 0: None of the terms above are found +** 1: There is a "word MATCH" term with $str in filter.argv[0]. +** 2: There is a "distance<" term with $value in filter.argv[0]. +** 3: Both "word MATCH" and "distance<" with $str in argv[0] and +** $value in argv[1]. +*/ static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - + int iPlan = 0; + int iDistTerm = -1; + int i; + const struct sqlite3_index_constraint *pConstraint; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( (iPlan & 1)==0 + && pConstraint->iColumn==0 + && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH + ){ + iPlan |= 1; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + } + if( (iPlan & 2)==0 + && pConstraint->iColumn==1 + && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT + || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE) + ){ + iPlan |= 2; + iDistTerm = i; + } + } + if( iPlan==2 ){ + pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1; + }else if( iPlan==3 ){ + pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 2; + } + pIdxInfo->idxNum = iPlan; + if( pIdxInfo->nOrderBy==1 + && pIdxInfo->aOrderBy[0].iColumn==1 + && pIdxInfo->aOrderBy[0].desc==0 + ){ + pIdxInfo->orderByConsumed = 1; + } + pIdxInfo->estimatedCost = (double)10000; + return SQLITE_OK; } @@ -274,8 +540,8 @@ static int fuzzerUpdate( int nFrom; const char *zTo; int nTo; - float rCost; - if( argc!=8 ){ + fuzzer_cost rCost; + if( argc!=7 ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf("cannot delete from a %s virtual table", p->zClassName); @@ -295,7 +561,7 @@ static int fuzzerUpdate( /* Silently ignore null transformations */ return SQLITE_OK; } - rCost = (float)sqlite3_value_double(argv[6]); + rCost = sqlite3_value_int(argv[6]); if( rCost<=0 ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf("cost must be positive"); @@ -309,8 +575,10 @@ static int fuzzerUpdate( return SQLITE_NOMEM; } pRule->zFrom = &pRule->zTo[nTo]; + pRule->nFrom = nFrom; memcpy(pRule->zFrom, zFrom, nFrom); memcpy(pRule->zTo, zTo, nTo); + pRule->nTo = nTo; pRule->rCost = rCost; pRule->pNext = p->pNewRule; p->pNewRule = pRule; diff --git a/test/fuzzer1.test b/test/fuzzer1.test index 418bba5506..1e33556aa3 100644 --- a/test/fuzzer1.test +++ b/test/fuzzer1.test @@ -31,9 +31,15 @@ do_test fuzzer1-1.1 { } {} do_test fuzzer1-1.2 { db eval { - INSERT INTO f1(cfrom, cto, cost) VALUES('e','a',0.1); - INSERT INTO f1(cfrom, cto, cost) VALUES('a','e',0.1); - INSERT INTO f1(cfrom, cto, cost) VALUES('e','o',0.1); + INSERT INTO f1(cfrom, cto, cost) VALUES('e','a',1); + INSERT INTO f1(cfrom, cto, cost) VALUES('a','e',1); + INSERT INTO f1(cfrom, cto, cost) VALUES('e','o',2); + } +} {} + +do_test fuzzer1-1.3 { + db eval { + SELECT word, distance FROM f1 WHERE word MATCH 'abcde' } } {} From d50deeeb7ad1279f17d49ef778ac6f2deac87b3e Mon Sep 17 00:00:00 2001 From: shaneh Date: Tue, 29 Mar 2011 05:06:46 +0000 Subject: [PATCH 04/31] In-progress changes - do not use; Removed prefix support; Added file control interface to enable/disable and adjust chunk size; added app-def function for same; FossilOrigin-Name: bc02d0c193225bd49a8d8a3295aeac752d3c2e30 --- manifest | 18 ++- manifest.uuid | 2 +- src/test_multiplex.c | 325 ++++++++++++++++++++++++------------------- src/test_multiplex.h | 48 +++++++ test/multiplex.test | 47 ++++--- 5 files changed, 263 insertions(+), 177 deletions(-) create mode 100644 src/test_multiplex.h diff --git a/manifest b/manifest index 5ec64793db..f83b7c380f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\smultiplex\sfile\snames\sto\sbe\spreceeded\sby\sprefix\sof\sthe\sform\s":multiplex:chunksize:maxchunks:"\s\nStill\swork\sto\sbe\sdone,\sthough\sit\scompiles\sand\sprefixes\sare\signored. -D 2011-03-15T04:45:48.735 +C In-progress\schanges\s-\sdo\snot\suse;\sRemoved\sprefix\ssupport;\sAdded\sfile\scontrol\sinterface\sto\senable/disable\sand\sadjust\schunk\ssize;\nadded\sapp-def\sfunction\sfor\ssame; +D 2011-03-29T05:06:46.821 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,7 +209,8 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c cf01141845d29639de2b6cdd6d7ef9dc0bce2888 +F src/test_multiplex.c 234f4b371d1a2ba88041e17c21e13f5273dd1b50 +F src/test_multiplex.h 22238a3286817918f1975a7c523827ea45d9fbb4 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c @@ -575,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test 92a4839213fd8cba8b59f86d42b7a1da1857db39 +F test/multiplex.test b813d11f2cd6a15c64d85b97c0c009afc2168226 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -913,10 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P def98fd23e42bda13547e38ab13fed0e6554ce99 -R 324244b8e2a2e32cd06c5dbee5aab290 -T *branch * experimental -T *sym-experimental * -T -sym-trunk * +P cfa4a2f7ea948be0925227efca82baea509249c9 +R cd848b3ee75fe87902bd71c01c78919c U shaneh -Z b5732ca362c3f4ec7a64142aa2707561 +Z 7951456e7d17419744e4f948b8232fcd diff --git a/manifest.uuid b/manifest.uuid index ad05a9f286..9ab9b53bfe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cfa4a2f7ea948be0925227efca82baea509249c9 \ No newline at end of file +bc02d0c193225bd49a8d8a3295aeac752d3c2e30 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 694f7b4cb6..3855050edd 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -23,6 +23,10 @@ #include #include #include "sqliteInt.h" +#include "test_multiplex.h" + +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 /* ** For a build without mutexes, no-op the mutex calls. @@ -43,13 +47,13 @@ #define SQLITE_MULTIPLEX_VFS_NAME "multiplex" /* This is the limit on the chunk size. It may be changed by calling -** the sqlite3_multiplex_set() interface. +** the xFileControl() interface. */ #define SQLITE_MULTIPLEX_CHUNK_SIZE 0x40000000 /* 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 sqlite3_multiplex_set() interface. +** the xFileControl() interface. */ #define SQLITE_MULTIPLEX_MAX_CHUNKS 32 @@ -84,6 +88,9 @@ struct multiplexGroup { char *zName; /* Base filename of this group */ int nName; /* Length of base filename */ int flags; /* Flags used for original opening */ + int nChunkSize; /* Chunk size used for this group */ + int nMaxChunks; /* Max number of chunks for this group */ + int bEnabled; /* TRUE to use Multiplex VFS for this file */ multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */ }; @@ -142,11 +149,6 @@ static struct { */ multiplexGroup *pGroups; - /* Chunk params. - */ - int nChunkSize; - int nMaxChunks; - /* Storage for temp file names. Allocated during ** initialization to the max pathname of the underlying VFS. */ @@ -168,7 +170,7 @@ static void multiplexLeave(void){ sqlite3_mutex_leave(gMultiplex.pMutex); } static sqlite3_file *multiplexSubOpen(multiplexConn *pConn, int iChunk, int *rc, int *pOutFlags){ multiplexGroup *pGroup = pConn->pGroup; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - if( iChunknMaxChunks ){ sqlite3_file *pSubOpen = pGroup->pReal[iChunk]; /* Real file descriptor */ if( !pGroup->bOpen[iChunk] ){ memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); @@ -193,51 +195,34 @@ static sqlite3_file *multiplexSubOpen(multiplexConn *pConn, int iChunk, int *rc, return NULL; } -/* -** If the given filename begins with a valid multiplex prefix, return -** a pointer to the first character past the prefix. Otherwise -** return NULL pointer. If optional chunk size and max chunk -** values found, return them in int pointers. -*/ -static const char *multiplexParsePrefix(const char *zName, int *pChunkSize, int *pMaxChunks){ - int i; - int nChunkSize = 0; - int nMaxChunks = 0; - int lenPrefix = sqlite3Strlen30(SQLITE_MULTIPLEX_VFS_NAME)+2; - if( strncmp(zName, ":"SQLITE_MULTIPLEX_VFS_NAME":", lenPrefix)!=0 ) return 0; - /* if :multiplex: followed by ':' terminated string of digits, use - ** that value for the chunk size. */ - for(i=lenPrefix; sqlite3Isdigit(zName[i]); i++){ } - if ( zName[i]==':' ){ - if( pChunkSize ){ - if( sqlite3GetInt32(&zName[lenPrefix], &nChunkSize) ){ - *pChunkSize = nChunkSize; - } - } - lenPrefix = i+1; - /* if chunksize followed by ':' terminated string of digits, use - ** that value for the max chunks. */ - for(i=lenPrefix; sqlite3Isdigit(zName[i]); i++){ } - if ( zName[i]==':' ) { - if( pMaxChunks ){ - if( sqlite3GetInt32(&zName[lenPrefix], &nMaxChunks) ){ - *pMaxChunks = nMaxChunks; - } - } - lenPrefix = i+1; - } +static void multiplexControlFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + extern const char *sqlite3TestErrorName(int); + extern int multiplexFileControl(sqlite3_file *, int, void *); + sqlite3_file *db = (sqlite3_file *)sqlite3_user_data(context); + int op = sqlite3_value_int(argv[0]); + int iVal = sqlite3_value_int(argv[1]); + int rc = multiplexFileControl(db, op, &iVal); + if( rc== 0 ){ + sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); } - return &zName[lenPrefix]; + sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); } /* -** If the given filename that may or may not begin with a CEROD prefix, return -** a pointer to the first character of the filename past the prefix. +** This is the entry point to register the extension for the multiplex_control() function. */ -static const char *multiplexRootFilename(const char *zName){ - const char *zRoot = multiplexParsePrefix(zName, NULL, NULL); - if( zRoot==0 ) zRoot = zName; - return zRoot; +static int multiplexFuncInit( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, + db, multiplexControlFunc, 0, 0); + return 0; } /************************* VFS Method Wrappers *****************************/ @@ -274,9 +259,9 @@ static int multiplexOpen( pMultiplexOpen = (multiplexConn*)pConn; /* allocate space for group */ sz = sizeof(multiplexGroup) /* multiplexGroup */ - + (sizeof(sqlite3_file *)*gMultiplex.nMaxChunks) /* pReal[] */ - + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks) /* *pReal */ - + gMultiplex.nMaxChunks /* bOpen[] */ + + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */ + + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */ + + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */ + nName + 1; /* zName */ #ifndef SQLITE_MULTIPLEX_EXT_OVWR sz += SQLITE_MULTIPLEX_EXT_SZ; @@ -293,14 +278,17 @@ static int multiplexOpen( char *p = (char *)&pGroup[1]; pMultiplexOpen->pGroup = pGroup; memset(pGroup, 0, sz); + pGroup->nChunkSize = SQLITE_MULTIPLEX_CHUNK_SIZE; + pGroup->nMaxChunks = SQLITE_MULTIPLEX_MAX_CHUNKS; pGroup->pReal = (sqlite3_file **)p; - p += (sizeof(sqlite3_file *)*gMultiplex.nMaxChunks); - for(i=0; inMaxChunks); + for(i=0; inMaxChunks; i++){ pGroup->pReal[i] = (sqlite3_file *)p; p += pOrigVfs->szOsFile; } + /* bOpen[] vals should all be zero from memset above */ pGroup->bOpen = p; - p += gMultiplex.nMaxChunks; + p += pGroup->nMaxChunks; pGroup->zName = p; /* save off base filename, name length, and original open flags */ memcpy(pGroup->zName, zName, nName+1); @@ -344,7 +332,7 @@ static int multiplexDelete( multiplexEnter(); memcpy(gMultiplex.zName, zName, nName+1); - for(i=0; ixAccess(pOrigVfs, multiplexRootFilename(gMultiplex.zName), SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, delete it */ - rc2 = pOrigVfs->xDelete(pOrigVfs, multiplexRootFilename(gMultiplex.zName), syncDir); + rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir); if( rc2!=SQLITE_OK ) rc = rc2; }else{ /* stop at first "gap" */ @@ -368,19 +356,11 @@ static int multiplexDelete( return rc; } -static int multiplexAccess(sqlite3_vfs *pVfs, const char *zName,int flgs,int *pOut){ - return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, multiplexRootFilename(zName), flgs, pOut); +static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){ + return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d); } -static int multiplexFullPathname(sqlite3_vfs *pVfs, const char *zName, int nOut, char *zOut){ - int n; - const char *zBase; - zBase = multiplexParsePrefix(zName, NULL, NULL); - if( zBase==0 ){ - return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, zName, nOut, zOut); - } - n = (int)(zBase - zName); - memcpy(zOut, zName, n); - return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, zBase, nOut - n, &zOut[n]); +static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){ + return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d); } static void *multiplexDlOpen(sqlite3_vfs *a, const char *b){ return gMultiplex.pOrigVfs->xDlOpen(gMultiplex.pOrigVfs, b); @@ -424,7 +404,7 @@ static int multiplexClose(sqlite3_file *pConn){ int i; multiplexEnter(); /* close any open handles */ - for(i=0; inMaxChunks; i++){ if( pGroup->bOpen[i] ){ sqlite3_file *pSubOpen = pGroup->pReal[i]; int rc2 = pSubOpen->pMethods->xClose(pSubOpen); @@ -455,16 +435,17 @@ static int multiplexRead( sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; + multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); while( iAmt > 0 ){ - int i = (int)(iOfst/gMultiplex.nChunkSize); + int i = (int)(iOfst / pGroup->nChunkSize); sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); if( pSubOpen ){ - int extra = ((int)(iOfst % gMultiplex.nChunkSize) + iAmt) - gMultiplex.nChunkSize; + int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; if( extra<0 ) extra = 0; iAmt -= extra; - rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst%gMultiplex.nChunkSize); + rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); if( rc!=SQLITE_OK ) break; pBuf = (char *)pBuf + iAmt; iOfst += iAmt; @@ -489,16 +470,17 @@ static int multiplexWrite( sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; + multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); while( iAmt > 0 ){ - int i = (int)(iOfst/gMultiplex.nChunkSize); + int i = (int)(iOfst / pGroup->nChunkSize); sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); if( pSubOpen ){ - int extra = ((int)(iOfst % gMultiplex.nChunkSize) + iAmt) - gMultiplex.nChunkSize; + int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; if( extra<0 ) extra = 0; iAmt -= extra; - rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst%gMultiplex.nChunkSize); + rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); if( rc!=SQLITE_OK ) break; pBuf = (char *)pBuf + iAmt; iOfst += iAmt; @@ -527,7 +509,7 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexEnter(); memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); /* delete the chunks above the truncate limit */ - for(i=(int)(size/gMultiplex.nChunkSize)+1; inChunkSize)+1; inMaxChunks; i++){ /* close any open chunks before deleting them */ if( pGroup->bOpen[i] ){ pSubOpen = pGroup->pReal[i]; @@ -540,12 +522,12 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ #else sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); #endif - rc2 = pOrigVfs->xDelete(pOrigVfs, multiplexRootFilename(gMultiplex.zName), 0); + rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0); if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; } - pSubOpen = multiplexSubOpen(p, (int)(size/gMultiplex.nChunkSize), &rc2, NULL); + pSubOpen = multiplexSubOpen(p, (int)(size / pGroup->nChunkSize), &rc2, NULL); if( pSubOpen ){ - rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size%gMultiplex.nChunkSize); + rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->nChunkSize); if( rc2!=SQLITE_OK ) rc = rc2; }else{ rc = SQLITE_IOERR_TRUNCATE; @@ -562,7 +544,7 @@ static int multiplexSync(sqlite3_file *pConn, int flags){ int rc = SQLITE_OK; int i; multiplexEnter(); - for(i=0; inMaxChunks; i++){ /* if we don't have it open, we don't need to sync it */ if( pGroup->bOpen[i] ){ sqlite3_file *pSubOpen = pGroup->pReal[i]; @@ -585,7 +567,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ int i; multiplexEnter(); *pSize = 0; - for(i=0; inMaxChunks; i++){ sqlite3_file *pSubOpen = NULL; /* if not opened already, check to see if the chunk exists */ if( pGroup->bOpen[i] ){ @@ -601,7 +583,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); #endif } - rc2 = pOrigVfs->xAccess(pOrigVfs, multiplexRootFilename(gMultiplex.zName), SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, open it */ pSubOpen = multiplexSubOpen(p, i, &rc, NULL); @@ -616,7 +598,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ if( rc2!=SQLITE_OK ){ rc = rc2; }else{ - if( sz>gMultiplex.nChunkSize ){ + if( sz>pGroup->nChunkSize ){ rc = SQLITE_IOERR_FSTAT; } *pSize += sz; @@ -669,14 +651,49 @@ static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){ */ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ multiplexConn *p = (multiplexConn*)pConn; - int rc; + multiplexGroup *pGroup = p->pGroup; + int rc = SQLITE_ERROR; sqlite3_file *pSubOpen; - if ( op==SQLITE_FCNTL_SIZE_HINT || op==SQLITE_FCNTL_CHUNK_SIZE ) return SQLITE_OK; + + if( !gMultiplex.isInitialized ) return SQLITE_MISUSE; + switch( op ){ + case MULTIPLEX_CTRL_ENABLE: + if( pArg ) { + int bEnabled = *(int *)pArg; + pGroup->bEnabled = bEnabled; + rc = SQLITE_OK; + } + break; + case MULTIPLEX_CTRL_SET_CHUNK_SIZE: + if( pArg ) { + int nChunkSize = *(int *)pArg; + if( nChunkSize<32 ){ + rc = SQLITE_MISUSE; + }else{ + pGroup->nChunkSize = nChunkSize; + rc = SQLITE_OK; + } + } + break; + case MULTIPLEX_CTRL_SET_MAX_CHUNKS: + if( pArg ) { + int nMaxChunks = *(int *)pArg; + if(( nMaxChunks<1 ) || ( nMaxChunks>99 )){ + rc = SQLITE_MISUSE; + }else{ + pGroup->nMaxChunks = nMaxChunks; + rc = SQLITE_OK; + } + } + break; + default: pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); if( pSubOpen ){ - return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); + rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); } - return SQLITE_ERROR; + break; + } + return rc; } /* Pass xSectorSize requests through to the original VFS unchanged. @@ -788,8 +805,6 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ sqlite3_mutex_free(gMultiplex.pMutex); return SQLITE_NOMEM; } - gMultiplex.nChunkSize = SQLITE_MULTIPLEX_CHUNK_SIZE; - gMultiplex.nMaxChunks = SQLITE_MULTIPLEX_MAX_CHUNKS; gMultiplex.pGroups = NULL; gMultiplex.isInitialized = 1; gMultiplex.pOrigVfs = pOrigVfs; @@ -830,6 +845,9 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier; gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap; sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault); + + sqlite3_auto_extension((void*)multiplexFuncInit); + return SQLITE_OK; } @@ -853,33 +871,10 @@ int sqlite3_multiplex_shutdown(void){ return SQLITE_OK; } -/* -** Adjust chunking params. VFS should be initialized first. -** No files should be open. Re-intializing will reset these -** to the default. -*/ -int sqlite3_multiplex_set( - int nChunkSize, /* Max chunk size */ - int nMaxChunks /* Max number of chunks */ -){ - if( !gMultiplex.isInitialized ) return SQLITE_MISUSE; - if( gMultiplex.pGroups ) return SQLITE_MISUSE; - if( nChunkSize<32 ) return SQLITE_MISUSE; - if( nMaxChunks<1 ) return SQLITE_MISUSE; - if( nMaxChunks>99 ) return SQLITE_MISUSE; - multiplexEnter(); - gMultiplex.nChunkSize = nChunkSize; - gMultiplex.nMaxChunks = nMaxChunks; - multiplexLeave(); - return SQLITE_OK; -} - /***************************** Test Code ***********************************/ #ifdef SQLITE_TEST #include -extern const char *sqlite3TestErrorName(int); - /* ** tclcmd: sqlite3_multiplex_initialize NAME MAKEDEFAULT @@ -937,36 +932,6 @@ static int test_multiplex_shutdown( return TCL_OK; } -/* -** tclcmd: sqlite3_multiplex_set CHUNK_SIZE MAX_CHUNKS -*/ -static int test_multiplex_set( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int nChunkSize; /* Max chunk size */ - int nMaxChunks; /* Max number of chunks */ - int rc; /* Value returned by sqlite3_multiplex_set() */ - - UNUSED_PARAMETER(clientData); - - /* Process arguments */ - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "CHUNK_SIZE MAX_CHUNKS"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[1], &nChunkSize) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[2], &nMaxChunks) ) return TCL_ERROR; - - /* Invoke sqlite3_multiplex_set() */ - rc = sqlite3_multiplex_set(nChunkSize, nMaxChunks); - - Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); - return TCL_OK; -} - /* ** tclcmd: sqlite3_multiplex_dump */ @@ -1000,16 +965,16 @@ static int test_multiplex_dump( Tcl_NewIntObj(pGroup->flags)); /* count number of chunks with open handles */ - for(i=0; inMaxChunks; i++){ if( pGroup->bOpen[i] ) nChunks++; } Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(nChunks)); Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(gMultiplex.nChunkSize)); + Tcl_NewIntObj(pGroup->nChunkSize)); Tcl_ListObjAppendElement(interp, pGroupTerm, - Tcl_NewIntObj(gMultiplex.nMaxChunks)); + Tcl_NewIntObj(pGroup->nMaxChunks)); Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); } @@ -1018,6 +983,72 @@ static int test_multiplex_dump( return TCL_OK; } +/* +** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE? +*/ +static int test_multiplex_control( + ClientData cd, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; /* Return code from file_control() */ + int idx; /* Index in aSub[] */ + Tcl_CmdInfo cmdInfo; /* Command info structure for HANDLE */ + sqlite3 *db; /* Underlying db handle for HANDLE */ + int iValue = 0; + void *pArg = 0; + + struct SubCommand { + const char *zName; + int op; + int argtype; + } aSub[] = { + { "enable", MULTIPLEX_CTRL_ENABLE, 1 }, + { "chunk_size", MULTIPLEX_CTRL_SET_CHUNK_SIZE, 1 }, + { "max_chunks", MULTIPLEX_CTRL_SET_MAX_CHUNKS, 1 }, + { 0, 0, 0 } + }; + + if( objc!=4 && objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND ?INT-VALUE?"); + return TCL_ERROR; + } + + if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ + Tcl_AppendResult(interp, "expected database handle, got \"", 0); + Tcl_AppendResult(interp, Tcl_GetString(objv[1]), "\"", 0); + return TCL_ERROR; + }else{ + db = *(sqlite3 **)cmdInfo.objClientData; + } + + rc = Tcl_GetIndexFromObjStruct( + interp, objv[3], aSub, sizeof(aSub[0]), "sub-command", 0, &idx + ); + if( rc!=TCL_OK ) return rc; + + switch( aSub[idx].argtype ){ + case 1: + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 4, objv, "INT-VALUE"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[4], &iValue) ){ + return TCL_ERROR; + } + pArg = (void *)&iValue; + break; + default: + Tcl_WrongNumArgs(interp, 4, objv, "SUB-COMMAND"); + return TCL_ERROR; + } + + rc = sqlite3_file_control(db, Tcl_GetString(objv[2]), aSub[idx].op, pArg); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); + return (rc==SQLITE_OK) ? TCL_OK : TCL_ERROR; +} + /* ** This routine registers the custom TCL commands defined in this ** module. This should be the only procedure visible from outside @@ -1030,8 +1061,8 @@ int Sqlitemultiplex_Init(Tcl_Interp *interp){ } aCmd[] = { { "sqlite3_multiplex_initialize", test_multiplex_initialize }, { "sqlite3_multiplex_shutdown", test_multiplex_shutdown }, - { "sqlite3_multiplex_set", test_multiplex_set }, { "sqlite3_multiplex_dump", test_multiplex_dump }, + { "sqlite3_multiplex_control", test_multiplex_control }, }; int i; diff --git a/src/test_multiplex.h b/src/test_multiplex.h new file mode 100644 index 0000000000..cc56ee92e4 --- /dev/null +++ b/src/test_multiplex.h @@ -0,0 +1,48 @@ +/* +** 2011 March 18 +** +** 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 a VFS "shim" - a layer that sits in between the +** pager and the real VFS. +** +** This particular shim enforces a multiplex system on DB files. +** This shim shards/partitions a single DB file into smaller +** "chunks" such that the total DB file size may exceed the maximum +** file size of the underlying file system. +** +*/ + +#ifndef _TEST_MULTIPLEX_H +#define _TEST_MULTIPLEX_H + +/* +** CAPI: File-control Operations Supported by Multiplex VFS +** +** Values interpreted by the xFileControl method of a Multiplex VFS db file-handle. +** +** MULTIPLEX_CTRL_ENABLE: +** This file control is used to enable or disable the multiplex +** shim. +** +** MULTIPLEX_CTRL_SET_CHUNK_SIZE: +** This file control is used to set the maximum allowed chunk +** size for a multiplex file set. +** +** MULTIPLEX_CTRL_SET_MAX_CHUNKS: +** This file control is used to set the maximum number of chunks +** allowed to be used for a mutliplex file set. +*/ +#define MULTIPLEX_CTRL_ENABLE 214014 +#define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015 +#define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016 + + +#endif diff --git a/test/multiplex.test b/test/multiplex.test index 742ca5079e..582f71eabe 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -32,13 +32,17 @@ proc multiplex_name {name chunk} { } # This saves off the parameters and calls the -# underlying sqlite3_multiplex_set() API. -proc multiplex_set {chunk_size max_chunks} { +# underlying sqlite3_multiplex_control() API. +proc multiplex_set {db name chunk_size max_chunks} { global g_chunk_size global g_max_chunks set g_chunk_size $chunk_size set g_max_chunks $max_chunks - sqlite3_multiplex_set $chunk_size $max_chunks + set rc [catch {sqlite3_multiplex_control $db $name chunk_size $chunk_size} msg] + if { $rc==0 } { + set rc [catch {sqlite3_multiplex_control $db $name max_chunks $max_chunks} msg] + } + list $msg } # This attempts to delete the base file and @@ -71,14 +75,15 @@ do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.9 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.10.1 { multiplex_set 32768 16 } {SQLITE_OK} -do_test multiplex-1.10.2 { multiplex_set 32768 -1 } {SQLITE_MISUSE} -do_test multiplex-1.10.3 { multiplex_set -1 16 } {SQLITE_MISUSE} -do_test multiplex-1.10.4 { multiplex_set 31 16 } {SQLITE_MISUSE} -do_test multiplex-1.10.5 { multiplex_set 32768 100 } {SQLITE_MISUSE} +sqlite3 db test.db +do_test multiplex-1.10.1 { multiplex_set db main 32768 16 } {SQLITE_OK} +do_test multiplex-1.10.2 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE} +do_test multiplex-1.10.3 { multiplex_set db main -1 16 } {SQLITE_MISUSE} +do_test multiplex-1.10.4 { multiplex_set db main 31 16 } {SQLITE_MISUSE} +do_test multiplex-1.10.5 { multiplex_set db main 32768 100 } {SQLITE_MISUSE} +db close do_test multiplex-1.11 { sqlite3_multiplex_shutdown } {SQLITE_OK} - #------------------------------------------------------------------------- # Some simple warm-body tests with a single database file in rollback # mode: @@ -89,7 +94,7 @@ do_test multiplex-1.11 { sqlite3_multiplex_shutdown } {SQLITE_OK} # # multiplex-2.3.*: Open and close a second db. # -# multiplex-2.4.*: Try to shutdown the multiplex system before closing the db +# multiplex-2.4.*: Try to shutdown the multiplex system befor e closing the db # file. Check that this fails and the multiplex system still works # afterwards. Then close the database and successfully shut # down the multiplex system. @@ -100,7 +105,7 @@ do_test multiplex-1.11 { sqlite3_multiplex_shutdown } {SQLITE_OK} # well as varying journal mode. sqlite3_multiplex_initialize "" 1 -multiplex_set 32768 16 +multiplex_set db main 32768 16 do_test multiplex-2.1.2 { sqlite3 db test.db @@ -130,6 +135,7 @@ do_test multiplex-2.3.1 { db2 close } {} + do_test multiplex-2.4.1 { sqlite3_multiplex_shutdown } {SQLITE_MISUSE} @@ -146,11 +152,11 @@ do_test multiplex-2.4.99 { do_test multiplex-2.5.1 { multiplex_delete test.db sqlite3_multiplex_initialize "" 1 - multiplex_set 4096 16 + sqlite3 db test.db + multiplex_set db main 4096 16 } {SQLITE_OK} do_test multiplex-2.5.2 { - sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = delete; @@ -197,6 +203,9 @@ do_test multiplex-2.5.99 { sqlite3_multiplex_shutdown } {SQLITE_OK} +return + +# TBD fix the below set all_journal_modes {delete persist truncate memory off} foreach jmode $all_journal_modes { @@ -205,7 +214,7 @@ foreach jmode $all_journal_modes { do_test multiplex-2.6.1.$sz.$jmode { multiplex_delete test.db sqlite3_multiplex_initialize "" 1 - multiplex_set $sz 32 + multiplex_set db main $sz 32 } {SQLITE_OK} do_test multiplex-2.6.2.$sz.$jmode { @@ -255,7 +264,7 @@ foreach jmode $all_journal_modes { do_test multiplex-3.1.1 { multiplex_delete test.db sqlite3_multiplex_initialize "" 1 - multiplex_set 32768 16 + multiplex_set db main 32768 16 } {SQLITE_OK} do_test multiplex-3.1.2 { sqlite3 db test.db @@ -341,7 +350,7 @@ do_test multiplex-3.2.X { # sqlite3_multiplex_initialize "" 1 -multiplex_set 32768 16 +multiplex_set db main 32768 16 # Return a list of all currently defined multiplexs. proc multiplex_list {} { @@ -403,7 +412,7 @@ do_test multiplex-4.1.12 { # sqlite3_multiplex_initialize "" 1 -multiplex_set 32768 16 +multiplex_set db main 32768 16 do_faultsim_test multiplex-5.1 -prep { catch {db close} @@ -448,7 +457,7 @@ do_faultsim_test multiplex-5.5 -prep { catch { sqlite3_multiplex_shutdown } } -body { sqlite3_multiplex_initialize "" 1 - multiplex_set 32768 16 + multiplex_set db main 32768 16 } # test that mismatch filesize is detected @@ -481,7 +490,7 @@ if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} { } db close sqlite3_multiplex_initialize "" 1 - multiplex_set 4096 16 + multiplex_set db main 4096 16 sqlite3 db test.db } {} do_test multiplex-5.6.3.$jmode { From 72384dc28f14b186d3211fc0181cda9ea3b7516f Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Mar 2011 14:08:09 +0000 Subject: [PATCH 05/31] Further improvements to the fuzzer. It still is not quite working. Pausing to work on other things.... FossilOrigin-Name: 5f2f2fce40f43debeb0492c9b460b85c7dad2bde --- install-sh | 0 manifest | 30 +++------ manifest.uuid | 2 +- src/test_fuzzer.c | 153 ++++++++++++++++++++++++++++++--------------- test/fuzzer1.test | 4 +- test/progress.test | 0 tool/mkopts.tcl | 0 7 files changed, 114 insertions(+), 75 deletions(-) mode change 100644 => 100755 install-sh mode change 100755 => 100644 test/progress.test mode change 100755 => 100644 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100644 new mode 100755 diff --git a/manifest b/manifest index a9cd7caec3..8148ffca72 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Added\smost\sof\sthe\slogic.\s\sSimple\stest\sruns\swithout\ssegfaulting\sbut\sdoes\snot\ngive\sthe\scorrect\sanswer. -D 2011-03-26T19:04:47.346 +C Further\simprovements\sto\sthe\sfuzzer.\s\sIt\sstill\sis\snot\squite\sworking.\s\sPausing\nto\swork\son\sother\sthings.... +D 2011-03-29T14:08:09.188 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -102,7 +99,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 +F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F main.mk a767e12162f02719fa94697a6ff0c8b51bcd62a6 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a @@ -205,7 +202,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c 133c830fdd4342b687910a04cf8e617e0f5f0e5f +F src/test_fuzzer.c 3e402dd5e6c4f096fdc92c52e775e8fad85bce9b F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -479,7 +476,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/fuzzer1.test e0fe96bb8d318250b35407954c7059eea8ea77b2 +F test/fuzzer1.test a5d60f618443b86b5f5a695a41d01b7d8697345d F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d @@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x +F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8 @@ -896,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,14 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P ea3a4ee136ff6699c3099178f0efaa8bb517715f -R 6a09f2dbc53bf6a269c56104914ae3e5 +P fb4c31eac8a7290f61c50a3552245660e1271871 +R 86b6649d084e41c015babc3a0e3fb294 U drh -Z c40c33ca74d9ed106c795140b6ad71ee ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFNjjjSoxKgR168RlERAjfMAKCJigUMIbnNV83nhVCWCpDK5WxPFQCeLIbS -+J80DLXre8S3k4SR8glB8Jc= -=nBDg ------END PGP SIGNATURE----- +Z 67d6460bdc70fd366585e4c8607ab8f4 diff --git a/manifest.uuid b/manifest.uuid index 54187bc30b..09a1e57cc7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb4c31eac8a7290f61c50a3552245660e1271871 \ No newline at end of file +5f2f2fce40f43debeb0492c9b460b85c7dad2bde \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index e4aca40fc8..82f35a2f51 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -49,7 +50,15 @@ struct fuzzer_rule { }; /* -** A stem object is used to generate variants. +** A stem object is used to generate variants. It is also used to record +** previously generated outputs. +** +** Every stem is added to a hash table as it is output. Generation of +** duplicate stems is suppressed. +** +** Active stems (those that might generate new outputs) are kepts on a linked +** list sorted by increasing cost. The cost is the sum of rBaseCost and +** pRule->rCost. */ struct fuzzer_stem { char *zBasis; /* Word being fuzzed */ @@ -83,6 +92,7 @@ struct fuzzer_cursor { fuzzer_stem *pDone; /* Stems already processed to completion */ char *zBuf; /* Temporary use buffer */ int nBuf; /* Bytes allocated for zBuf */ + fuzzer_rule nullRule; /* Null rule used first */ fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */ }; @@ -171,7 +181,6 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ memset(pCur, 0, sizeof(*pCur)); pCur->pVtab = p; *ppCursor = &pCur->base; - p->nCursor++; if( p->nCursor==0 && p->pNewRule ){ unsigned int i; fuzzer_rule *pX; @@ -191,6 +200,7 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ } p->pRule = fuzzerMergeRules(p->pRule, pX); } + p->nCursor++; return SQLITE_OK; } @@ -221,35 +231,34 @@ static int fuzzerClose(sqlite3_vtab_cursor *cur){ fuzzerClearCursor(pCur, 0); sqlite3_free(pCur->zBuf); pCur->pVtab->nCursor--; + sqlite3_free(pCur); return SQLITE_OK; } /* ** Compute the current output term for a fuzzer_stem. */ -static int fuzzerComputeWord( - fuzzer_cursor *pCur, - fuzzer_stem *pStem +static int fuzzerRender( + fuzzer_stem *pStem, /* The stem to be rendered */ + char **pzBuf, /* Write results into this buffer. realloc if needed */ + int *pnBuf /* Size of the buffer */ ){ const fuzzer_rule *pRule = pStem->pRule; int n; + char *z; - n = pStem->nBasis; - if( pStem->n>=0 ) n += pRule->nTo - pRule->nFrom; - if( pCur->nBufzBuf = sqlite3_realloc(pCur->zBuf, n+100); - if( pCur->zBuf==0 ) return SQLITE_NOMEM; - pCur->nBuf = n+100; + n = pStem->nBasis + pRule->nTo - pRule->nFrom; + if( (*pnBuf)n; - if( n<0 ){ - memcpy(pCur->zBuf, pStem->zBasis, pStem->nBasis+1); - }else{ - memcpy(pCur->zBuf, pStem->zBasis, n); - memcpy(&pCur->zBuf[n], pRule->zTo, pRule->nTo); - memcpy(&pCur->zBuf[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], - pStem->nBasis-n-pRule->nFrom+1); - } + z = *pzBuf; + memcpy(z, pStem->zBasis, n); + memcpy(&z[n], pRule->zTo, pRule->nTo); + memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], + pStem->nBasis-n-pRule->nFrom+1); return SQLITE_OK; } @@ -260,7 +269,7 @@ static int fuzzerComputeWord( static unsigned int fuzzerHash(const char *z){ unsigned int h = 0; while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); } - return h%10007; + return h % FUZZER_HASH; } /* @@ -270,9 +279,30 @@ static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){ return pStem->rBaseCost + pStem->pRule->rCost; } +/* +** Return 1 if the string to which the cursor is point has already +** been emitted. Return 0 if not. Return -1 on a memory allocation +** failures. +*/ +static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){ + unsigned int h; + fuzzer_stem *pLookup; + + if( fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){ + return -1; + } + h = fuzzerHash(pCur->zBuf); + pLookup = pCur->apHash[h]; + while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){ + pLookup = pLookup->pHash; + } + return pLookup!=0; +} + /* ** Advance a fuzzer_stem to its next value. Return 0 if there are -** no more values that can be generated by this fuzzer_stem. +** no more values that can be generated by this fuzzer_stem. Return +** -1 on a memory allocation failure. */ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ const fuzzer_rule *pRule; @@ -283,21 +313,14 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ || memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0 ){ /* Found a rewrite case. Make sure it is not a duplicate */ - unsigned int h; - fuzzer_stem *pLookup; - - fuzzerComputeWord(pCur, pStem); - h = fuzzerHash(pCur->zBuf); - pLookup = pCur->apHash[h]; - while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){ - pLookup = pLookup->pHash; - } - if( pLookup==0 ) return 1; /* A new output is found. */ + int rc = fuzzerSeen(pCur, pStem); + if( rc<0 ) return -1; + if( rc==0 ) return 1; } } pStem->n = -1; pStem->pRule = pRule->pNext; - if( fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0; + if( pStem->pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0; } return 0; } @@ -310,6 +333,10 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ static fuzzer_stem *fuzzerInsert(fuzzer_stem *pList, fuzzer_stem *pNew){ fuzzer_cost c1; + if( pList==0 ){ + pNew->pNext = 0; + return pNew; + } c1 = fuzzerCost(pNew); if( c1 <= fuzzerCost(pList) ){ pNew->pNext = pList; @@ -358,20 +385,30 @@ static fuzzer_stem *fuzzerNewStem( ** Advance a cursor to its next row of output */ static int fuzzerNext(sqlite3_vtab_cursor *cur){ - fuzzer_cursor *pCur = (fuzzer_cursor*)pCur; + fuzzer_cursor *pCur = (fuzzer_cursor*)cur; + int rc; fuzzer_stem *pStem, *pNew; /* Use the element the cursor is currently point to to create ** a new stem and insert the new stem into the priority queue. */ - fuzzerComputeWord(pCur, pCur->pStem); - pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pCur->pStem)); - if( pNew ){ - if( fuzzerAdvance(pCur, pNew)==0 ){ - pNew->pNext = pCur->pDone; - pCur->pDone = pNew; + pStem = pCur->pStem; + if( fuzzerCost(pStem)>0 ){ + rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf); + if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM; + pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pStem)); + if( pNew ){ + if( fuzzerAdvance(pCur, pNew)==0 ){ + pNew->pNext = pCur->pDone; + pCur->pDone = pNew; + }else{ + pCur->pStem = fuzzerInsert(pStem, pNew); + if( pCur->pStem==pNew ){ + return SQLITE_OK; + } + } }else{ - pCur->pStem = fuzzerInsert(pCur->pStem, pNew); + return SQLITE_NOMEM; } } @@ -381,7 +418,12 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){ while( (pStem = pCur->pStem)!=0 ){ if( fuzzerAdvance(pCur, pStem) ){ pCur->pStem = fuzzerInsert(pStem->pNext, pStem); - return SQLITE_OK; /* New word found */ + if( pCur->pStem!=pStem && (rc = fuzzerSeen(pCur, pStem))!=0 ){ + if( rc<0 ) return SQLITE_NOMEM; + continue; + }else{ + return SQLITE_OK; /* New word found */ + } } pCur->pStem = pStem->pNext; pStem->pNext = pCur->pDone; @@ -406,9 +448,10 @@ static int fuzzerFilter( ){ fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor; const char *zWord = 0; - pCur->rLimit = 2147483647; + fuzzer_stem *pStem; fuzzerClearCursor(pCur, 1); + pCur->rLimit = 2147483647; if( idxNum==1 ){ zWord = (const char*)sqlite3_value_text(argv[0]); }else if( idxNum==2 ){ @@ -418,8 +461,15 @@ static int fuzzerFilter( pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[1]); } if( zWord==0 ) zWord = ""; - pCur->pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0); - if( pCur->pStem==0 ) return SQLITE_NOMEM; + pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0); + if( pStem==0 ) return SQLITE_NOMEM; + pCur->nullRule.pNext = pCur->pVtab->pRule; + pCur->nullRule.rCost = 0; + pCur->nullRule.nFrom = 0; + pCur->nullRule.nTo = 0; + pCur->nullRule.zFrom = ""; + pStem->pRule = &pCur->nullRule; + pStem->n = pStem->nBasis; return SQLITE_OK; } @@ -431,7 +481,7 @@ static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ fuzzer_cursor *pCur = (fuzzer_cursor*)cur; if( i==0 ){ /* the "word" column */ - if( fuzzerComputeWord(pCur, pCur->pStem)==SQLITE_NOMEM ){ + if( fuzzerRender(pCur->pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){ return SQLITE_NOMEM; } sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); @@ -567,17 +617,16 @@ static int fuzzerUpdate( pVTab->zErrMsg = sqlite3_mprintf("cost must be positive"); return SQLITE_CONSTRAINT; } - nFrom = strlen(zFrom)+1; - nTo = strlen(zTo)+1; - if( nTo<4 ) nTo = 4; - pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo - 4 ); + nFrom = strlen(zFrom); + nTo = strlen(zTo); + pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo ); if( pRule==0 ){ return SQLITE_NOMEM; } - pRule->zFrom = &pRule->zTo[nTo]; + pRule->zFrom = &pRule->zTo[nTo+1]; pRule->nFrom = nFrom; - memcpy(pRule->zFrom, zFrom, nFrom); - memcpy(pRule->zTo, zTo, nTo); + memcpy(pRule->zFrom, zFrom, nFrom+1); + memcpy(pRule->zTo, zTo, nTo+1); pRule->nTo = nTo; pRule->rCost = rCost; pRule->pNext = p->pNewRule; diff --git a/test/fuzzer1.test b/test/fuzzer1.test index 1e33556aa3..aaceaf1ce1 100644 --- a/test/fuzzer1.test +++ b/test/fuzzer1.test @@ -32,8 +32,8 @@ do_test fuzzer1-1.1 { do_test fuzzer1-1.2 { db eval { INSERT INTO f1(cfrom, cto, cost) VALUES('e','a',1); - INSERT INTO f1(cfrom, cto, cost) VALUES('a','e',1); - INSERT INTO f1(cfrom, cto, cost) VALUES('e','o',2); + INSERT INTO f1(cfrom, cto, cost) VALUES('a','e',10); + INSERT INTO f1(cfrom, cto, cost) VALUES('e','o',100); } } {} diff --git a/test/progress.test b/test/progress.test old mode 100755 new mode 100644 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 From c8e27ab5da2192c526f4b81f1fc10fe32506b5dc Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Mar 2011 18:21:59 +0000 Subject: [PATCH 06/31] The first simple test-case appears to be working now. FossilOrigin-Name: dd41155bc7459cafc1a2d5c75233193abfbac05d --- manifest | 14 +++++------ manifest.uuid | 2 +- src/test_fuzzer.c | 60 +++++++++++++++++++++++++++++++++++++++-------- test/fuzzer1.test | 2 +- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 8148ffca72..20d5dc398c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\sthe\sfuzzer.\s\sIt\sstill\sis\snot\squite\sworking.\s\sPausing\nto\swork\son\sother\sthings.... -D 2011-03-29T14:08:09.188 +C The\sfirst\ssimple\stest-case\sappears\sto\sbe\sworking\snow. +D 2011-03-29T18:21:59.753 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -202,7 +202,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c 3e402dd5e6c4f096fdc92c52e775e8fad85bce9b +F src/test_fuzzer.c 1427f9b54dbb6fa4742bd611adcd9b0abedfc083 F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -476,7 +476,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/fuzzer1.test a5d60f618443b86b5f5a695a41d01b7d8697345d +F test/fuzzer1.test a81a50d7ba6005d9cc98bf58b8aae8c3e73e11a6 F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d @@ -918,7 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P fb4c31eac8a7290f61c50a3552245660e1271871 -R 86b6649d084e41c015babc3a0e3fb294 +P 5f2f2fce40f43debeb0492c9b460b85c7dad2bde +R 1ce7df4d179ed6c133db387973d1e6f3 U drh -Z 67d6460bdc70fd366585e4c8607ab8f4 +Z 6cf1874f37d2b9758d183fd9153a451e diff --git a/manifest.uuid b/manifest.uuid index 09a1e57cc7..98b1b08a7b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5f2f2fce40f43debeb0492c9b460b85c7dad2bde \ No newline at end of file +dd41155bc7459cafc1a2d5c75233193abfbac05d \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index 82f35a2f51..9a5f8c5930 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -255,14 +255,17 @@ static int fuzzerRender( } n = pStem->n; z = *pzBuf; - memcpy(z, pStem->zBasis, n); - memcpy(&z[n], pRule->zTo, pRule->nTo); - memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], - pStem->nBasis-n-pRule->nFrom+1); + if( n<0 ){ + memcpy(z, pStem->zBasis, pStem->nBasis+1); + }else{ + memcpy(z, pStem->zBasis, n); + memcpy(&z[n], pRule->zTo, pRule->nTo); + memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], + pStem->nBasis-n-pRule->nFrom+1); + } return SQLITE_OK; } - /* ** Compute a hash on zBasis. */ @@ -279,6 +282,35 @@ static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){ return pStem->rBaseCost + pStem->pRule->rCost; } +#if 0 +/* +** Print a description of a fuzzer_stem on stderr. +*/ +static void fuzzerStemPrint( + const char *zPrefix, + fuzzer_stem *pStem, + const char *zSuffix +){ + if( pStem->n<0 ){ + fprintf(stderr, "%s[%s](%d)-->self%s", + zPrefix, + pStem->zBasis, pStem->rBaseCost, + zSuffix + ); + }else{ + char *zBuf = 0; + int nBuf = 0; + if( fuzzerRender(pStem, &zBuf, &nBuf)!=SQLITE_OK ) return; + fprintf(stderr, "%s[%s](%d)-->{%s}(%d)%s", + zPrefix, + pStem->zBasis, pStem->rBaseCost, zBuf, fuzzerCost(pStem), + zSuffix + ); + sqlite3_free(zBuf); + } +} +#endif + /* ** Return 1 if the string to which the cursor is point has already ** been emitted. Return 0 if not. Return -1 on a memory allocation @@ -315,7 +347,9 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ /* Found a rewrite case. Make sure it is not a duplicate */ int rc = fuzzerSeen(pCur, pStem); if( rc<0 ) return -1; - if( rc==0 ) return 1; + if( rc==0 ){ + return 1; + } } } pStem->n = -1; @@ -417,17 +451,23 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){ */ while( (pStem = pCur->pStem)!=0 ){ if( fuzzerAdvance(pCur, pStem) ){ - pCur->pStem = fuzzerInsert(pStem->pNext, pStem); - if( pCur->pStem!=pStem && (rc = fuzzerSeen(pCur, pStem))!=0 ){ + pCur->pStem = pStem = fuzzerInsert(pStem->pNext, pStem); + if( (rc = fuzzerSeen(pCur, pStem))!=0 ){ if( rc<0 ) return SQLITE_NOMEM; continue; - }else{ - return SQLITE_OK; /* New word found */ } + return SQLITE_OK; /* New word found */ } pCur->pStem = pStem->pNext; pStem->pNext = pCur->pDone; pCur->pDone = pStem; + if( pCur->pStem ){ + rc = fuzzerSeen(pCur, pCur->pStem); + if( rc<0 ) return SQLITE_NOMEM; + if( rc==0 ){ + return SQLITE_OK; + } + } } /* Reach this point only if queue has been exhausted and there is diff --git a/test/fuzzer1.test b/test/fuzzer1.test index aaceaf1ce1..895d6b3b2a 100644 --- a/test/fuzzer1.test +++ b/test/fuzzer1.test @@ -41,7 +41,7 @@ do_test fuzzer1-1.3 { db eval { SELECT word, distance FROM f1 WHERE word MATCH 'abcde' } -} {} +} {abcde 0 abcda 1 ebcde 10 ebcda 11 abcdo 100 ebcdo 110 obcde 110 obcda 111 obcdo 210} finish_test From f938a87cfdb990d655ded1f954c45c46cf6e6a81 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Mar 2011 23:41:31 +0000 Subject: [PATCH 07/31] Add support for rowid. FossilOrigin-Name: 2cf4158ff051916717fc2c0f4b6332d5f6ea6e3d --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test_fuzzer.c | 9 +++++++-- tool/mkopts.tcl | 0 4 files changed, 15 insertions(+), 10 deletions(-) mode change 100644 => 100755 tool/mkopts.tcl diff --git a/manifest b/manifest index 20d5dc398c..10d2ec544b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sfirst\ssimple\stest-case\sappears\sto\sbe\sworking\snow. -D 2011-03-29T18:21:59.753 +C Add\ssupport\sfor\srowid. +D 2011-03-29T23:41:31.447 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -202,7 +202,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c 1427f9b54dbb6fa4742bd611adcd9b0abedfc083 +F src/test_fuzzer.c dcb1e78badcf6f469ae386ecbed0e287920699c6 F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -893,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -918,7 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 5f2f2fce40f43debeb0492c9b460b85c7dad2bde -R 1ce7df4d179ed6c133db387973d1e6f3 +P dd41155bc7459cafc1a2d5c75233193abfbac05d +R 580275be924edc1c171a4ef2518a45c4 U drh -Z 6cf1874f37d2b9758d183fd9153a451e +Z c835c92c0dd7f7913ad85caf0a4ef7ac diff --git a/manifest.uuid b/manifest.uuid index 98b1b08a7b..398d9aafa8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dd41155bc7459cafc1a2d5c75233193abfbac05d \ No newline at end of file +2cf4158ff051916717fc2c0f4b6332d5f6ea6e3d \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index 9a5f8c5930..5287b1f457 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -86,6 +86,7 @@ struct fuzzer_vtab { /* A fuzzer cursor object */ struct fuzzer_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3_int64 iRowid; /* The rowid of the current word */ fuzzer_vtab *pVtab; /* The virtual table this cursor belongs to */ fuzzer_cost rLimit; /* Maximum cost of any term */ fuzzer_stem *pStem; /* Sorted list of stems for generating new terms */ @@ -423,6 +424,8 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){ int rc; fuzzer_stem *pStem, *pNew; + pCur->iRowid++; + /* Use the element the cursor is currently point to to create ** a new stem and insert the new stem into the priority queue. */ @@ -510,6 +513,7 @@ static int fuzzerFilter( pCur->nullRule.zFrom = ""; pStem->pRule = &pCur->nullRule; pStem->n = pStem->nBasis; + pCur->iRowid = 1; return SQLITE_OK; } @@ -536,10 +540,11 @@ static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ } /* -** The rowid is always 0 +** The rowid. */ static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - *pRowid = 0; /* The rowid is always 0 */ + fuzzer_cursor *pCur = (fuzzer_cursor*)cur; + *pRowid = pCur->iRowid; return SQLITE_OK; } diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 2a0e00b436f94594307cb989cc1235be3011864e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Mar 2011 01:43:00 +0000 Subject: [PATCH 08/31] Move to an O(NlogN) algorithm for the priority queue. An insertion sort was way too slow. FossilOrigin-Name: 7958cbba736a599c1293b06602eec43dfe4fd7d1 --- manifest | 12 ++-- manifest.uuid | 2 +- src/test_fuzzer.c | 174 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 141 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 10d2ec544b..7aec386c02 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssupport\sfor\srowid. -D 2011-03-29T23:41:31.447 +C Move\sto\san\sO(NlogN)\salgorithm\sfor\sthe\spriority\squeue.\s\sAn\sinsertion\ssort\nwas\sway\stoo\sslow. +D 2011-03-30T01:43:00.780 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -202,7 +202,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c dcb1e78badcf6f469ae386ecbed0e287920699c6 +F src/test_fuzzer.c edc2aaa0f75ce49efef39bcd2df45138479b0992 F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -918,7 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P dd41155bc7459cafc1a2d5c75233193abfbac05d -R 580275be924edc1c171a4ef2518a45c4 +P 2cf4158ff051916717fc2c0f4b6332d5f6ea6e3d +R 9250685bf3b3b21491f862d4fc8952d0 U drh -Z c835c92c0dd7f7913ad85caf0a4ef7ac +Z 0b9911f371ac67382b47460caefb0a30 diff --git a/manifest.uuid b/manifest.uuid index 398d9aafa8..dfc8e61028 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2cf4158ff051916717fc2c0f4b6332d5f6ea6e3d \ No newline at end of file +7958cbba736a599c1293b06602eec43dfe4fd7d1 \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index 5287b1f457..ffdd61c9f6 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -66,6 +66,7 @@ struct fuzzer_stem { const fuzzer_rule *pRule; /* Current rule to apply */ int n; /* Apply pRule at this character offset */ fuzzer_cost rBaseCost; /* Base cost of getting to zBasis */ + fuzzer_cost rCostX; /* Precomputed rBaseCost + pRule->rCost */ fuzzer_stem *pNext; /* Next stem in rCost order */ fuzzer_stem *pHash; /* Next stem with same hash on zBasis */ }; @@ -82,6 +83,7 @@ struct fuzzer_vtab { }; #define FUZZER_HASH 4001 /* Hash table size */ +#define FUZZER_NQUEUE 20 /* Number of slots on the stem queue */ /* A fuzzer cursor object */ struct fuzzer_cursor { @@ -89,10 +91,13 @@ struct fuzzer_cursor { sqlite3_int64 iRowid; /* The rowid of the current word */ fuzzer_vtab *pVtab; /* The virtual table this cursor belongs to */ fuzzer_cost rLimit; /* Maximum cost of any term */ - fuzzer_stem *pStem; /* Sorted list of stems for generating new terms */ + fuzzer_stem *pStem; /* Stem with smallest rCostX */ fuzzer_stem *pDone; /* Stems already processed to completion */ + fuzzer_stem *aQueue[FUZZER_NQUEUE]; /* Queue of stems with higher rCostX */ + int mxQueue; /* Largest used index in aQueue[] */ char *zBuf; /* Temporary use buffer */ int nBuf; /* Bytes allocated for zBuf */ + int nStem; /* Number of stems allocated */ fuzzer_rule nullRule; /* Null rule used first */ fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */ }; @@ -205,23 +210,35 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ return SQLITE_OK; } +/* +** Free all stems in a list. +*/ +static void fuzzerClearStemList(fuzzer_stem *pStem){ + while( pStem ){ + fuzzer_stem *pNext = pStem->pNext; + sqlite3_free(pStem); + pStem = pNext; + } +} + /* ** Free up all the memory allocated by a cursor. Set it rLimit to 0 ** to indicate that it is at EOF. */ static void fuzzerClearCursor(fuzzer_cursor *pCur, int clearHash){ - if( pCur->pStem==0 && pCur->pDone==0 ) clearHash = 0; - do{ - while( pCur->pStem ){ - fuzzer_stem *pStem = pCur->pStem; - pCur->pStem = pStem->pNext; - sqlite3_free(pStem); - } - pCur->pStem = pCur->pDone; - pCur->pDone = 0; - }while( pCur->pStem ); + int i; + fuzzerClearStemList(pCur->pStem); + fuzzerClearStemList(pCur->pDone); + for(i=0; iaQueue[i]); pCur->rLimit = (fuzzer_cost)0; - if( clearHash ) memset(pCur->apHash, 0, sizeof(pCur->apHash)); + if( clearHash && pCur->nStem ){ + pCur->mxQueue = 0; + pCur->pStem = 0; + pCur->pDone = 0; + memset(pCur->aQueue, 0, sizeof(pCur->aQueue)); + memset(pCur->apHash, 0, sizeof(pCur->apHash)); + } + pCur->nStem = 0; } /* @@ -280,7 +297,7 @@ static unsigned int fuzzerHash(const char *z){ ** Current cost of a stem */ static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){ - return pStem->rBaseCost + pStem->pRule->rCost; + return pStem->rCostX = pStem->rBaseCost + pStem->pRule->rCost; } #if 0 @@ -304,7 +321,7 @@ static void fuzzerStemPrint( if( fuzzerRender(pStem, &zBuf, &nBuf)!=SQLITE_OK ) return; fprintf(stderr, "%s[%s](%d)-->{%s}(%d)%s", zPrefix, - pStem->zBasis, pStem->rBaseCost, zBuf, fuzzerCost(pStem), + pStem->zBasis, pStem->rBaseCost, zBuf, pStem->, zSuffix ); sqlite3_free(zBuf); @@ -349,6 +366,7 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ int rc = fuzzerSeen(pCur, pStem); if( rc<0 ) return -1; if( rc==0 ){ + fuzzerCost(pStem); return 1; } } @@ -361,31 +379,106 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){ } /* -** Insert pNew into the list at pList. Return a pointer to the new +** The two input stem lists are both sorted in order of increasing +** rCostX. Merge them together into a single list, sorted by rCostX, and +** return a pointer to the head of that new list. +*/ +static fuzzer_stem *fuzzerMergeStems(fuzzer_stem *pA, fuzzer_stem *pB){ + fuzzer_stem head; + fuzzer_stem *pTail; + + pTail = &head; + while( pA && pB ){ + if( pA->rCostX<=pB->rCostX ){ + pTail->pNext = pA; + pTail = pA; + pA = pA->pNext; + }else{ + pTail->pNext = pB; + pTail = pB; + pB = pB->pNext; + } + } + if( pA==0 ){ + pTail->pNext = pB; + }else{ + pTail->pNext = pA; + } + return head.pNext; +} + +/* +** Load pCur->pStem with the lowest-cost stem. Return a pointer +** to the lowest-cost stem. +*/ +static fuzzer_stem *fuzzerLowestCostStem(fuzzer_cursor *pCur){ + fuzzer_stem *pBest, *pX; + int iBest; + int i; + + if( pCur->pStem==0 ){ + iBest = -1; + pBest = 0; + for(i=0; i<=pCur->mxQueue; i++){ + pX = pCur->aQueue[i]; + if( pX==0 ) continue; + if( pBest==0 || pBest->rCostX>pX->rCostX ){ + pBest = pX; + iBest = i; + } + } + if( pBest ){ + pCur->aQueue[iBest] = pBest->pNext; + pBest->pNext = 0; + pCur->pStem = pBest; + } + } + return pCur->pStem; +} + +/* +** Insert pNew into queue of pending stems. Then find the stem +** with the lowest rCostX and move it into pCur->pStem. ** list. The insert is done such the pNew is in the correct order ** according to fuzzer_stem.zBaseCost+fuzzer_stem.pRule->rCost. */ -static fuzzer_stem *fuzzerInsert(fuzzer_stem *pList, fuzzer_stem *pNew){ - fuzzer_cost c1; +static fuzzer_stem *fuzzerInsert(fuzzer_cursor *pCur, fuzzer_stem *pNew){ + fuzzer_stem *pX; + int i; - if( pList==0 ){ + /* If pCur->pStem exists and is greater than pNew, then make pNew + ** the new pCur->pStem and insert the old pCur->pStem instead. + */ + if( (pX = pCur->pStem)!=0 && pX->rCostX>pNew->rCostX ){ pNew->pNext = 0; - return pNew; + pCur->pStem = pNew; + pNew = pX; } - c1 = fuzzerCost(pNew); - if( c1 <= fuzzerCost(pList) ){ - pNew->pNext = pList; - return pNew; - }else{ - fuzzer_stem *pPrev; - pPrev = pList; - while( pPrev->pNext && fuzzerCost(pPrev->pNext)pNext; + + /* Insert the new value */ + pNew->pNext = 0; + pX = pNew; + for(i=0; i<=pCur->mxQueue; i++){ + if( pCur->aQueue[i] ){ + pX = fuzzerMergeStems(pX, pCur->aQueue[i]); + pCur->aQueue[i] = 0; + }else{ + pCur->aQueue[i] = pX; + break; } - pNew->pNext = pPrev->pNext; - pPrev->pNext = pNew; - return pList; } + if( i>pCur->mxQueue ){ + if( imxQueue = i; + pCur->aQueue[i] = pX; + }else{ + assert( pCur->mxQueue==FUZZER_NQUEUE-1 ); + pX = fuzzerMergeStems(pX, pCur->aQueue[FUZZER_NQUEUE-1]); + pCur->aQueue[FUZZER_NQUEUE-1] = pX; + } + } + + return fuzzerLowestCostStem(pCur); } /* @@ -408,10 +501,11 @@ static fuzzer_stem *fuzzerNewStem( memcpy(pNew->zBasis, zWord, pNew->nBasis+1); pNew->pRule = pCur->pVtab->pRule; pNew->n = -1; - pNew->rBaseCost = rBaseCost; + pNew->rBaseCost = pNew->rCostX = rBaseCost; h = fuzzerHash(pNew->zBasis); pNew->pHash = pCur->apHash[h]; pCur->apHash[h] = pNew; + pCur->nStem++; return pNew; } @@ -430,17 +524,16 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){ ** a new stem and insert the new stem into the priority queue. */ pStem = pCur->pStem; - if( fuzzerCost(pStem)>0 ){ + if( pStem->rCostX>0 ){ rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf); if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM; - pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pStem)); + pNew = fuzzerNewStem(pCur, pCur->zBuf, pStem->rCostX); if( pNew ){ if( fuzzerAdvance(pCur, pNew)==0 ){ pNew->pNext = pCur->pDone; pCur->pDone = pNew; }else{ - pCur->pStem = fuzzerInsert(pStem, pNew); - if( pCur->pStem==pNew ){ + if( fuzzerInsert(pCur, pNew)==pNew ){ return SQLITE_OK; } } @@ -454,17 +547,18 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){ */ while( (pStem = pCur->pStem)!=0 ){ if( fuzzerAdvance(pCur, pStem) ){ - pCur->pStem = pStem = fuzzerInsert(pStem->pNext, pStem); + pCur->pStem = 0; + pStem = fuzzerInsert(pCur, pStem); if( (rc = fuzzerSeen(pCur, pStem))!=0 ){ if( rc<0 ) return SQLITE_NOMEM; continue; } return SQLITE_OK; /* New word found */ } - pCur->pStem = pStem->pNext; + pCur->pStem = 0; pStem->pNext = pCur->pDone; pCur->pDone = pStem; - if( pCur->pStem ){ + if( fuzzerLowestCostStem(pCur) ){ rc = fuzzerSeen(pCur, pCur->pStem); if( rc<0 ) return SQLITE_NOMEM; if( rc==0 ){ @@ -531,7 +625,7 @@ static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT); }else if( i==1 ){ /* the "distance" column */ - sqlite3_result_int(ctx, fuzzerCost(pCur->pStem)); + sqlite3_result_int(ctx, pCur->pStem->rCostX); }else{ /* All other columns are NULL */ sqlite3_result_null(ctx); From ac039688d2b7f6a55b142efba59eea84e4047f34 Mon Sep 17 00:00:00 2001 From: shaneh Date: Wed, 30 Mar 2011 21:03:07 +0000 Subject: [PATCH 09/31] Updates to multiplex.test script; misc. bug fixes; FossilOrigin-Name: c41ff2358e8af0fe2186ab4173b81fba204a57ab --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test_multiplex.c | 23 ++++++++++++----------- test/multiplex.test | 11 ++++------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index f83b7c380f..66152d91b4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In-progress\schanges\s-\sdo\snot\suse;\sRemoved\sprefix\ssupport;\sAdded\sfile\scontrol\sinterface\sto\senable/disable\sand\sadjust\schunk\ssize;\nadded\sapp-def\sfunction\sfor\ssame; -D 2011-03-29T05:06:46.821 +C Updates\sto\smultiplex.test\sscript;\s\smisc.\sbug\sfixes; +D 2011-03-30T21:03:07.666 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,7 +209,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c 234f4b371d1a2ba88041e17c21e13f5273dd1b50 +F src/test_multiplex.c aa5da1f2847d6d6e69a41a6d8a9242860549258f F src/test_multiplex.h 22238a3286817918f1975a7c523827ea45d9fbb4 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec @@ -576,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test b813d11f2cd6a15c64d85b97c0c009afc2168226 +F test/multiplex.test 5e03b40ebdee38d5a75ebbf38a469abede9414de F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -914,7 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P cfa4a2f7ea948be0925227efca82baea509249c9 -R cd848b3ee75fe87902bd71c01c78919c +P bc02d0c193225bd49a8d8a3295aeac752d3c2e30 +R 48cf934a82b0a69cbaf131357eaf96fa U shaneh -Z 7951456e7d17419744e4f948b8232fcd +Z e448ef64d054580e4db4bcfd141ad84b diff --git a/manifest.uuid b/manifest.uuid index 9ab9b53bfe..78855b3796 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bc02d0c193225bd49a8d8a3295aeac752d3c2e30 \ No newline at end of file +c41ff2358e8af0fe2186ab4173b81fba204a57ab \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 3855050edd..a1768f0c4b 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -25,9 +25,6 @@ #include "sqliteInt.h" #include "test_multiplex.h" -#include "sqlite3ext.h" -SQLITE_EXTENSION_INIT1 - /* ** For a build without mutexes, no-op the mutex calls. */ @@ -216,13 +213,12 @@ static void multiplexControlFunc( ** This is the entry point to register the extension for the multiplex_control() function. */ static int multiplexFuncInit( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db ){ - sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, + int rc; + rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, db, multiplexControlFunc, 0, 0); - return 0; + return rc; } /************************* VFS Method Wrappers *****************************/ @@ -686,11 +682,16 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ } } break; + case SQLITE_FCNTL_SIZE_HINT: + case SQLITE_FCNTL_CHUNK_SIZE: + /* no-op these */ + rc = SQLITE_OK; + break; default: - pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); - if( pSubOpen ){ + pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); + if( pSubOpen ){ rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); - } + } break; } return rc; diff --git a/test/multiplex.test b/test/multiplex.test index 582f71eabe..ce76fdfeab 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -203,9 +203,6 @@ do_test multiplex-2.5.99 { sqlite3_multiplex_shutdown } {SQLITE_OK} -return - -# TBD fix the below set all_journal_modes {delete persist truncate memory off} foreach jmode $all_journal_modes { @@ -214,11 +211,11 @@ foreach jmode $all_journal_modes { do_test multiplex-2.6.1.$sz.$jmode { multiplex_delete test.db sqlite3_multiplex_initialize "" 1 + sqlite3 db test.db multiplex_set db main $sz 32 } {SQLITE_OK} do_test multiplex-2.6.2.$sz.$jmode { - sqlite3 db test.db db eval { PRAGMA page_size = 1024; PRAGMA auto_vacuum = off; @@ -264,10 +261,10 @@ foreach jmode $all_journal_modes { do_test multiplex-3.1.1 { multiplex_delete test.db sqlite3_multiplex_initialize "" 1 + sqlite3 db test.db multiplex_set db main 32768 16 } {SQLITE_OK} do_test multiplex-3.1.2 { - sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = delete; @@ -490,9 +487,9 @@ if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} { } db close sqlite3_multiplex_initialize "" 1 - multiplex_set db main 4096 16 sqlite3 db test.db - } {} + multiplex_set db main 4096 16 + } {SQLITE_OK} do_test multiplex-5.6.3.$jmode { catchsql { INSERT INTO t1 VALUES(6, randomblob(1100)); From 78c4de4c71d7ae69111090b3ed33bd83e78501b7 Mon Sep 17 00:00:00 2001 From: shaneh Date: Thu, 31 Mar 2011 05:31:24 +0000 Subject: [PATCH 10/31] Additional test cases; Round chunk size up to a multiple of max page size; FossilOrigin-Name: 36e364a3fe7d3a9a521189ff0262611a492c21dc --- manifest | 16 ++++++------- manifest.uuid | 2 +- src/test_multiplex.c | 54 +++++++++++++++++++++++++++++++++----------- src/test_multiplex.h | 45 +++++++++++++++++++++++++++++++++++- test/multiplex.test | 48 +++++++++++++++++++++++++-------------- 5 files changed, 125 insertions(+), 40 deletions(-) diff --git a/manifest b/manifest index 66152d91b4..266e9254d8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\smultiplex.test\sscript;\s\smisc.\sbug\sfixes; -D 2011-03-30T21:03:07.666 +C Additional\stest\scases;\s\sRound\schunk\ssize\sup\sto\sa\smultiple\sof\smax\spage\ssize; +D 2011-03-31T05:31:24.274 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,8 +209,8 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c aa5da1f2847d6d6e69a41a6d8a9242860549258f -F src/test_multiplex.h 22238a3286817918f1975a7c523827ea45d9fbb4 +F src/test_multiplex.c 6edf785c1ca9468f7d5ead21e73aeec350931588 +F src/test_multiplex.h 7bb4e7505e38996125d346177eab7ac4f8a2cbef F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c @@ -576,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test 5e03b40ebdee38d5a75ebbf38a469abede9414de +F test/multiplex.test e58dbe5b5a3b84a1f5b96408e29efdcd6f833f16 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -914,7 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P bc02d0c193225bd49a8d8a3295aeac752d3c2e30 -R 48cf934a82b0a69cbaf131357eaf96fa +P c41ff2358e8af0fe2186ab4173b81fba204a57ab +R 038c75157e031b60cfa85be2f04c19c6 U shaneh -Z e448ef64d054580e4db4bcfd141ad84b +Z 4af569247c03e0c4e633f1be2df20cf9 diff --git a/manifest.uuid b/manifest.uuid index 78855b3796..661c0bd7e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c41ff2358e8af0fe2186ab4173b81fba204a57ab \ No newline at end of file +36e364a3fe7d3a9a521189ff0262611a492c21dc \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index a1768f0c4b..ff3be68509 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -25,6 +25,11 @@ #include "sqliteInt.h" #include "test_multiplex.h" +#ifndef SQLITE_CORE + #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ +#endif +#include "sqlite3ext.h" + /* ** For a build without mutexes, no-op the mutex calls. */ @@ -44,9 +49,10 @@ #define SQLITE_MULTIPLEX_VFS_NAME "multiplex" /* This is the limit on the chunk size. It may be changed by calling -** the xFileControl() interface. +** the xFileControl() interface. It will be rounded up to a +** multiple of SQLITE_MAX_PAGE_SIZE. */ -#define SQLITE_MULTIPLEX_CHUNK_SIZE 0x40000000 +#define SQLITE_MULTIPLEX_CHUNK_SIZE (SQLITE_MAX_PAGE_SIZE*32) /* 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 @@ -199,12 +205,28 @@ static void multiplexControlFunc( ){ extern const char *sqlite3TestErrorName(int); extern int multiplexFileControl(sqlite3_file *, int, void *); - sqlite3_file *db = (sqlite3_file *)sqlite3_user_data(context); + // pPager->fd + sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); int op = sqlite3_value_int(argv[0]); int iVal = sqlite3_value_int(argv[1]); - int rc = multiplexFileControl(db, op, &iVal); - if( rc== 0 ){ - sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); + int rc = SQLITE_OK; + switch( op ){ + case 1: + op = MULTIPLEX_CTRL_ENABLE; + break; + case 2: + op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; + break; + case 3: + op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; + break; + default: + rc = SQLITE_ERROR; + break; + } + if( rc==SQLITE_OK ){ + sqlite3_file *f = (sqlite3_file *)db; + rc = multiplexFileControl(f, op, &iVal); } sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); } @@ -213,7 +235,9 @@ static void multiplexControlFunc( ** This is the entry point to register the extension for the multiplex_control() function. */ static int multiplexFuncInit( - sqlite3 *db + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ int rc; rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, @@ -663,9 +687,12 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ case MULTIPLEX_CTRL_SET_CHUNK_SIZE: if( pArg ) { int nChunkSize = *(int *)pArg; - if( nChunkSize<32 ){ + if( nChunkSize<1 ){ rc = SQLITE_MISUSE; }else{ + /* Round up to nearest multiple of SQLITE_MAX_PAGE_SIZE. */ + nChunkSize = (nChunkSize + (SQLITE_MAX_PAGE_SIZE-1)); + nChunkSize &= ~(SQLITE_MAX_PAGE_SIZE-1); pGroup->nChunkSize = nChunkSize; rc = SQLITE_OK; } @@ -674,7 +701,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ case MULTIPLEX_CTRL_SET_MAX_CHUNKS: if( pArg ) { int nMaxChunks = *(int *)pArg; - if(( nMaxChunks<1 ) || ( nMaxChunks>99 )){ + if(( nMaxChunks<1 ) || ( nMaxChunks>SQLITE_MULTIPLEX_MAX_CHUNKS )){ rc = SQLITE_MISUSE; }else{ pGroup->nMaxChunks = nMaxChunks; @@ -781,9 +808,10 @@ static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){ /************************** Public Interfaces *****************************/ /* -** Initialize the multiplex VFS shim. Use the VFS named zOrigVfsName -** as the VFS that does the actual work. Use the default if -** zOrigVfsName==NULL. +** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() +** +** Use the VFS named zOrigVfsName as the VFS that does the actual work. +** Use the default if zOrigVfsName==NULL. ** ** The multiplex VFS shim is named "multiplex". It will become the default ** VFS if makeDefault is non-zero. @@ -853,7 +881,7 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ } /* -** Shutdown the multiplex system. +** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() ** ** All SQLite database connections must be closed before calling this ** routine. diff --git a/src/test_multiplex.h b/src/test_multiplex.h index cc56ee92e4..a277e7afdb 100644 --- a/src/test_multiplex.h +++ b/src/test_multiplex.h @@ -34,7 +34,9 @@ ** ** MULTIPLEX_CTRL_SET_CHUNK_SIZE: ** This file control is used to set the maximum allowed chunk -** size for a multiplex file set. +** size for a multiplex file set. The chunk size should be +** a multiple of SQLITE_MAX_PAGE_SIZE, and will be rounded up +** if not. ** ** MULTIPLEX_CTRL_SET_MAX_CHUNKS: ** This file control is used to set the maximum number of chunks @@ -44,5 +46,46 @@ #define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015 #define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016 +/* +** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() +** +** Use the VFS named zOrigVfsName as the VFS that does the actual work. +** Use the default if zOrigVfsName==NULL. +** +** The multiplex VFS shim is named "multiplex". It will become the default +** VFS if makeDefault is non-zero. +** +** An auto-extension is registered which will make the function +** multiplex_control() available to open database connections. This +** function gives access to the xFileControl interface of the +** multiplex VFS shim. +** +** multiplex_control(,) +** +** =1 MULTIPLEX_CTRL_ENABLE +** =1 enable +** =2 disable +** +** =1 MULTIPLEX_CTRL_SET_CHUNK_SIZE +** int, chunk size +** +** =1 MULTIPLEX_CTRL_SET_MAX_CHUNKS +** int, max chunks +** +** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once +** during start-up. +*/ +extern int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault); + +/* +** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() +** +** All SQLite database connections must be closed before calling this +** routine. +** +** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while +** shutting down in order to free all remaining multiplex groups. +*/ +extern int sqlite3_multiplex_shutdown(void); #endif diff --git a/test/multiplex.test b/test/multiplex.test index ce76fdfeab..ab84c1e72c 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -36,7 +36,7 @@ proc multiplex_name {name chunk} { proc multiplex_set {db name chunk_size max_chunks} { global g_chunk_size global g_max_chunks - set g_chunk_size $chunk_size + set g_chunk_size [ expr (($chunk_size+($::SQLITE_MAX_PAGE_SIZE-1)) & ~($::SQLITE_MAX_PAGE_SIZE-1)) ] set g_max_chunks $max_chunks set rc [catch {sqlite3_multiplex_control $db $name chunk_size $chunk_size} msg] if { $rc==0 } { @@ -74,15 +74,27 @@ do_test multiplex-1.6 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.9 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -sqlite3 db test.db -do_test multiplex-1.10.1 { multiplex_set db main 32768 16 } {SQLITE_OK} -do_test multiplex-1.10.2 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE} -do_test multiplex-1.10.3 { multiplex_set db main -1 16 } {SQLITE_MISUSE} -do_test multiplex-1.10.4 { multiplex_set db main 31 16 } {SQLITE_MISUSE} -do_test multiplex-1.10.5 { multiplex_set db main 32768 100 } {SQLITE_MISUSE} -db close -do_test multiplex-1.11 { sqlite3_multiplex_shutdown } {SQLITE_OK} +do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.9.2 { sqlite3 db test.db } {} +do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK} +do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE} +do_test multiplex-1.9.5 { multiplex_set db main -1 16 } {SQLITE_MISUSE} +do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK} +do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_MISUSE} +do_test multiplex-1.9.8 { db close } {} +do_test multiplex-1.9.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} + +do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.10.2 { sqlite3 db test.db } {} +if { 0 } { +do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } } {SQLITE_OK} +do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } } {SQLITE_MISUSE} +do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } } {SQLITE_MISUSE} +do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } } {SQLITE_OK} +do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } } {SQLITE_MISUSE} +} +do_test multiplex-1.10.8 { db close } {} +do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} #------------------------------------------------------------------------- # Some simple warm-body tests with a single database file in rollback @@ -171,7 +183,9 @@ do_test multiplex-2.5.3 { INSERT INTO t1 VALUES(2, randomblob(4000)); INSERT INTO t1 VALUES(3, 'three'); INSERT INTO t1 VALUES(4, randomblob(4000)); - INSERT INTO t1 VALUES(5, 'five') + INSERT INTO t1 VALUES(5, 'five'); + INSERT INTO t1 VALUES(6, randomblob($g_chunk_size)); + INSERT INTO t1 VALUES(7, randomblob($g_chunk_size)); } } {} @@ -479,11 +493,11 @@ if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} { do_test multiplex-5.6.2.$jmode { execsql { CREATE TABLE t1(a, b); - INSERT INTO t1 VALUES(1, randomblob(1100)); - INSERT INTO t1 VALUES(2, randomblob(1100)); - INSERT INTO t1 VALUES(3, randomblob(1100)); - INSERT INTO t1 VALUES(4, randomblob(1100)); - INSERT INTO t1 VALUES(5, randomblob(1100)); + INSERT INTO t1 VALUES(1, randomblob(15000)); + INSERT INTO t1 VALUES(2, randomblob(15000)); + INSERT INTO t1 VALUES(3, randomblob(15000)); + INSERT INTO t1 VALUES(4, randomblob(15000)); + INSERT INTO t1 VALUES(5, randomblob(15000)); } db close sqlite3_multiplex_initialize "" 1 @@ -492,7 +506,7 @@ if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} { } {SQLITE_OK} do_test multiplex-5.6.3.$jmode { catchsql { - INSERT INTO t1 VALUES(6, randomblob(1100)); + INSERT INTO t1 VALUES(6, randomblob(15000)); } } {1 {disk I/O error}} do_test multiplex-5.6.4.$jmode { From d8ce22bbb7cb52e8bd3c19e4cddbc98821525217 Mon Sep 17 00:00:00 2001 From: shaneh Date: Thu, 31 Mar 2011 13:14:12 +0000 Subject: [PATCH 11/31] Tests and bug fixes for SELECT multiplex_control(op, val); Add tests and fixes for SELECT multiplex_control(op, val); FossilOrigin-Name: fee9734c193a8bec9599e02e16938179e642bf5e --- manifest | 16 +++++++-------- manifest.uuid | 2 +- src/test_multiplex.c | 49 +++++++++++++++++++++++++------------------- src/test_multiplex.h | 6 +++--- test/multiplex.test | 2 -- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/manifest b/manifest index 266e9254d8..d4d42b146b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Additional\stest\scases;\s\sRound\schunk\ssize\sup\sto\sa\smultiple\sof\smax\spage\ssize; -D 2011-03-31T05:31:24.274 +C Tests\sand\sbug\sfixes\sfor\sSELECT\smultiplex_control(op,\sval);\nAdd\stests\sand\sfixes\sfor\sSELECT\smultiplex_control(op,\sval); +D 2011-03-31T13:14:12.476 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,8 +209,8 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c 6edf785c1ca9468f7d5ead21e73aeec350931588 -F src/test_multiplex.h 7bb4e7505e38996125d346177eab7ac4f8a2cbef +F src/test_multiplex.c 07dff88008c801899680eec3b9b0ea30be9fba62 +F src/test_multiplex.h bf7b2d303688c32cdd1cee3ffdc377f13391e311 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c @@ -576,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test e58dbe5b5a3b84a1f5b96408e29efdcd6f833f16 +F test/multiplex.test 74009eeb9b1186855a56ad522f5daf9bcf6ee134 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -914,7 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P c41ff2358e8af0fe2186ab4173b81fba204a57ab -R 038c75157e031b60cfa85be2f04c19c6 +P 36e364a3fe7d3a9a521189ff0262611a492c21dc +R 139c8e5f53872b2a8fa7c9d64e54233c U shaneh -Z 4af569247c03e0c4e633f1be2df20cf9 +Z 22cc15d919103b40af9da38b0122d8bd diff --git a/manifest.uuid b/manifest.uuid index 661c0bd7e0..eb27bb55e1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36e364a3fe7d3a9a521189ff0262611a492c21dc \ No newline at end of file +fee9734c193a8bec9599e02e16938179e642bf5e \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index ff3be68509..214cddcaf1 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -205,34 +205,41 @@ static void multiplexControlFunc( ){ extern const char *sqlite3TestErrorName(int); extern int multiplexFileControl(sqlite3_file *, int, void *); - // pPager->fd - sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); - int op = sqlite3_value_int(argv[0]); - int iVal = sqlite3_value_int(argv[1]); int rc = SQLITE_OK; - switch( op ){ - case 1: - op = MULTIPLEX_CTRL_ENABLE; - break; - case 2: - op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; - break; - case 3: - op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; - break; - default: - rc = SQLITE_ERROR; - break; + sqlite3 *db = sqlite3_context_db_handle(context); + int op; + int iVal; + + if( !db || argc!=2 ){ + rc = SQLITE_ERROR; + }else{ + /* extract params */ + op = sqlite3_value_int(argv[0]); + iVal = sqlite3_value_int(argv[1]); + /* map function op to file_control op */ + switch( op ){ + case 1: + op = MULTIPLEX_CTRL_ENABLE; + break; + case 2: + op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; + break; + case 3: + op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; + break; + default: + rc = SQLITE_ERROR; + break; + } } if( rc==SQLITE_OK ){ - sqlite3_file *f = (sqlite3_file *)db; - rc = multiplexFileControl(f, op, &iVal); + rc = sqlite3_file_control(db, 0, op, &iVal); } sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); } /* -** This is the entry point to register the extension for the multiplex_control() function. +** This is the entry point to register the auto-extension for the multiplex_control() function. */ static int multiplexFuncInit( sqlite3 *db, @@ -241,7 +248,7 @@ static int multiplexFuncInit( ){ int rc; rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, - db, multiplexControlFunc, 0, 0); + 0, multiplexControlFunc, 0, 0); return rc; } diff --git a/src/test_multiplex.h b/src/test_multiplex.h index a277e7afdb..1a574c1a87 100644 --- a/src/test_multiplex.h +++ b/src/test_multiplex.h @@ -56,15 +56,15 @@ ** VFS if makeDefault is non-zero. ** ** An auto-extension is registered which will make the function -** multiplex_control() available to open database connections. This +** multiplex_control() available to database connections. This ** function gives access to the xFileControl interface of the ** multiplex VFS shim. ** -** multiplex_control(,) +** SELECT multiplex_control(,) ; ** ** =1 MULTIPLEX_CTRL_ENABLE +** =0 disable ** =1 enable -** =2 disable ** ** =1 MULTIPLEX_CTRL_SET_CHUNK_SIZE ** int, chunk size diff --git a/test/multiplex.test b/test/multiplex.test index ab84c1e72c..2d6642e243 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -86,13 +86,11 @@ do_test multiplex-1.9.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.10.2 { sqlite3 db test.db } {} -if { 0 } { do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } } {SQLITE_OK} do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } } {SQLITE_MISUSE} do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } } {SQLITE_MISUSE} do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } } {SQLITE_OK} do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } } {SQLITE_MISUSE} -} do_test multiplex-1.10.8 { db close } {} do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} From c27fa4b074777f6ca61a568e2c758909e7b75a6e Mon Sep 17 00:00:00 2001 From: shaneh Date: Thu, 31 Mar 2011 15:11:53 +0000 Subject: [PATCH 12/31] Enable/disable support. FossilOrigin-Name: b3c6d9aa9e2124a2f2a1a5f9dbbd7db3b1d01a31 --- manifest | 14 +-- manifest.uuid | 2 +- src/test_multiplex.c | 231 ++++++++++++++++++++++++------------------- test/multiplex.test | 88 +++++++++++++---- 4 files changed, 205 insertions(+), 130 deletions(-) diff --git a/manifest b/manifest index d4d42b146b..43d10d3845 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tests\sand\sbug\sfixes\sfor\sSELECT\smultiplex_control(op,\sval);\nAdd\stests\sand\sfixes\sfor\sSELECT\smultiplex_control(op,\sval); -D 2011-03-31T13:14:12.476 +C Enable/disable\ssupport. +D 2011-03-31T15:11:53.959 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,7 +209,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c 07dff88008c801899680eec3b9b0ea30be9fba62 +F src/test_multiplex.c c0d9450b63b0f785795e4873ce90002414921a61 F src/test_multiplex.h bf7b2d303688c32cdd1cee3ffdc377f13391e311 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec @@ -576,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test 74009eeb9b1186855a56ad522f5daf9bcf6ee134 +F test/multiplex.test 5373b2c3b0f3e262e746652d8f93b6f6297b15ba F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -914,7 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 36e364a3fe7d3a9a521189ff0262611a492c21dc -R 139c8e5f53872b2a8fa7c9d64e54233c +P fee9734c193a8bec9599e02e16938179e642bf5e +R 9ef3873d6c48b9ead5e6ba118b2bc91f U shaneh -Z 22cc15d919103b40af9da38b0122d8bd +Z 53dc1c2b6709916c1194488b48f81a5e diff --git a/manifest.uuid b/manifest.uuid index eb27bb55e1..1ae76db767 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fee9734c193a8bec9599e02e16938179e642bf5e \ No newline at end of file +b3c6d9aa9e2124a2f2a1a5f9dbbd7db3b1d01a31 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 214cddcaf1..a49825717e 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -50,9 +50,10 @@ /* This is the limit on the chunk size. It may be changed by calling ** the xFileControl() interface. It will be rounded up to a -** multiple of SQLITE_MAX_PAGE_SIZE. +** multiple of SQLITE_MAX_PAGE_SIZE. We default it here to 1GB. */ -#define SQLITE_MULTIPLEX_CHUNK_SIZE (SQLITE_MAX_PAGE_SIZE*32) +#define SQLITE_MULTIPLEX_CHUNK_SIZE (SQLITE_MAX_PAGE_SIZE*16384) + /* 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 @@ -305,6 +306,7 @@ static int multiplexOpen( char *p = (char *)&pGroup[1]; pMultiplexOpen->pGroup = pGroup; memset(pGroup, 0, sz); + pGroup->bEnabled = -1; pGroup->nChunkSize = SQLITE_MULTIPLEX_CHUNK_SIZE; pGroup->nMaxChunks = SQLITE_MULTIPLEX_MAX_CHUNKS; pGroup->pReal = (sqlite3_file **)p; @@ -323,6 +325,14 @@ static int multiplexOpen( pGroup->flags = flags; pSubOpen = multiplexSubOpen(pMultiplexOpen, 0, &rc, pOutFlags); if( pSubOpen ){ + /* if this file is already larger than chunk size, disable + ** the multiplex feature. + */ + sqlite3_int64 sz; + int rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); + if( (rc2==SQLITE_OK) && (sz>pGroup->nChunkSize) ){ + pGroup->bEnabled = 0; + } if( pSubOpen->pMethods->iVersion==1 ){ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1; }else{ @@ -465,21 +475,26 @@ static int multiplexRead( multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); - while( iAmt > 0 ){ - int i = (int)(iOfst / pGroup->nChunkSize); - sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); - if( pSubOpen ){ - int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; - if( extra<0 ) extra = 0; - iAmt -= extra; - rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); - if( rc!=SQLITE_OK ) break; - pBuf = (char *)pBuf + iAmt; - iOfst += iAmt; - iAmt = extra; - }else{ - rc = SQLITE_IOERR_READ; - break; + if( !pGroup->bEnabled ){ + sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); + rc = ( !pSubOpen ) ? SQLITE_IOERR_READ : pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst); + }else{ + while( iAmt > 0 ){ + int i = (int)(iOfst / pGroup->nChunkSize); + sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); + if( pSubOpen ){ + int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; + if( extra<0 ) extra = 0; + iAmt -= extra; + rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); + if( rc!=SQLITE_OK ) break; + pBuf = (char *)pBuf + iAmt; + iOfst += iAmt; + iAmt = extra; + }else{ + rc = SQLITE_IOERR_READ; + break; + } } } multiplexLeave(); @@ -500,21 +515,26 @@ static int multiplexWrite( multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); - while( iAmt > 0 ){ - int i = (int)(iOfst / pGroup->nChunkSize); - sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); - if( pSubOpen ){ - int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; - if( extra<0 ) extra = 0; - iAmt -= extra; - rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); - if( rc!=SQLITE_OK ) break; - pBuf = (char *)pBuf + iAmt; - iOfst += iAmt; - iAmt = extra; - }else{ - rc = SQLITE_IOERR_WRITE; - break; + if( !pGroup->bEnabled ){ + sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); + rc = ( !pSubOpen ) ? SQLITE_IOERR_WRITE : pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst); + }else{ + while( iAmt > 0 ){ + int i = (int)(iOfst / pGroup->nChunkSize); + sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL); + if( pSubOpen ){ + int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) - pGroup->nChunkSize; + if( extra<0 ) extra = 0; + iAmt -= extra; + rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->nChunkSize); + if( rc!=SQLITE_OK ) break; + pBuf = (char *)pBuf + iAmt; + iOfst += iAmt; + iAmt = extra; + }else{ + rc = SQLITE_IOERR_WRITE; + break; + } } } multiplexLeave(); @@ -529,35 +549,40 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; - int rc2; - int i; - sqlite3_file *pSubOpen; - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ multiplexEnter(); - memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); - /* delete the chunks above the truncate limit */ - for(i=(int)(size / pGroup->nChunkSize)+1; inMaxChunks; i++){ - /* close any open chunks before deleting them */ - if( pGroup->bOpen[i] ){ - pSubOpen = pGroup->pReal[i]; - rc2 = pSubOpen->pMethods->xClose(pSubOpen); - if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; - pGroup->bOpen[i] = 0; - } -#ifdef SQLITE_MULTIPLEX_EXT_OVWR - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); -#else - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); -#endif - rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0); - if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; - } - pSubOpen = multiplexSubOpen(p, (int)(size / pGroup->nChunkSize), &rc2, NULL); - if( pSubOpen ){ - rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->nChunkSize); - if( rc2!=SQLITE_OK ) rc = rc2; + if( !pGroup->bEnabled ){ + sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); + rc = ( !pSubOpen ) ? SQLITE_IOERR_TRUNCATE : pSubOpen->pMethods->xTruncate(pSubOpen, size); }else{ - rc = SQLITE_IOERR_TRUNCATE; + int rc2; + int i; + sqlite3_file *pSubOpen; + sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ + memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); + /* delete the chunks above the truncate limit */ + for(i=(int)(size / pGroup->nChunkSize)+1; inMaxChunks; i++){ + /* close any open chunks before deleting them */ + if( pGroup->bOpen[i] ){ + pSubOpen = pGroup->pReal[i]; + rc2 = pSubOpen->pMethods->xClose(pSubOpen); + if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; + pGroup->bOpen[i] = 0; + } +#ifdef SQLITE_MULTIPLEX_EXT_OVWR + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); +#else + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); +#endif + rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0); + if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; + } + pSubOpen = multiplexSubOpen(p, (int)(size / pGroup->nChunkSize), &rc2, NULL); + if( pSubOpen ){ + rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->nChunkSize); + if( rc2!=SQLITE_OK ) rc = rc2; + }else{ + rc = SQLITE_IOERR_TRUNCATE; + } } multiplexLeave(); return rc; @@ -593,46 +618,51 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ int rc2; int i; multiplexEnter(); - *pSize = 0; - for(i=0; inMaxChunks; i++){ - sqlite3_file *pSubOpen = NULL; - /* if not opened already, check to see if the chunk exists */ - if( pGroup->bOpen[i] ){ - pSubOpen = pGroup->pReal[i]; - }else{ - sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - int exists = 0; - memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); - if( i ){ -#ifdef SQLITE_MULTIPLEX_EXT_OVWR - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); -#else - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); -#endif - } - rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); - if( rc2==SQLITE_OK && exists){ - /* if it exists, open it */ - pSubOpen = multiplexSubOpen(p, i, &rc, NULL); + if( !pGroup->bEnabled ){ + sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL); + rc = ( !pSubOpen ) ? SQLITE_IOERR_FSTAT : pSubOpen->pMethods->xFileSize(pSubOpen, pSize); + }else{ + *pSize = 0; + for(i=0; inMaxChunks; i++){ + sqlite3_file *pSubOpen = NULL; + /* if not opened already, check to see if the chunk exists */ + if( pGroup->bOpen[i] ){ + pSubOpen = pGroup->pReal[i]; + }else{ + sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ + int exists = 0; + memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); + if( i ){ +#ifdef SQLITE_MULTIPLEX_EXT_OVWR + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); +#else + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); +#endif + } + rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); + if( rc2==SQLITE_OK && exists){ + /* if it exists, open it */ + pSubOpen = multiplexSubOpen(p, 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->nChunkSize ){ + rc = SQLITE_IOERR_FSTAT; + } + *pSize += sz; + } }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->nChunkSize ){ - rc = SQLITE_IOERR_FSTAT; - } - *pSize += sz; - } - }else{ - break; - } } multiplexLeave(); return rc; @@ -674,7 +704,8 @@ static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){ return SQLITE_IOERR_CHECKRESERVEDLOCK; } -/* Pass xFileControl requests through to the original VFS unchanged. +/* Pass xFileControl requests through to the original VFS unchanged, +** except for any MULTIPLEX_CTRL_* requests here. */ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ multiplexConn *p = (multiplexConn*)pConn; @@ -1046,8 +1077,8 @@ static int test_multiplex_control( { 0, 0, 0 } }; - if( objc!=4 && objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND ?INT-VALUE?"); + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND INT-VALUE"); return TCL_ERROR; } @@ -1066,10 +1097,6 @@ static int test_multiplex_control( switch( aSub[idx].argtype ){ case 1: - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 4, objv, "INT-VALUE"); - return TCL_ERROR; - } if( Tcl_GetIntFromObj(interp, objv[4], &iValue) ){ return TCL_ERROR; } diff --git a/test/multiplex.test b/test/multiplex.test index 2d6642e243..c76cee71a0 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -14,7 +14,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -set g_chunk_size 2147483648 +set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ] set g_max_chunks 32 # This handles appending the chunk number @@ -74,25 +74,44 @@ do_test multiplex-1.6 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.9.2 { sqlite3 db test.db } {} -do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK} -do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE} -do_test multiplex-1.9.5 { multiplex_set db main -1 16 } {SQLITE_MISUSE} -do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK} -do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_MISUSE} -do_test multiplex-1.9.8 { db close } {} -do_test multiplex-1.9.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.10.2 { sqlite3 db test.db } {} -do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } } {SQLITE_OK} -do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } } {SQLITE_MISUSE} -do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } } {SQLITE_MISUSE} -do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } } {SQLITE_OK} -do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } } {SQLITE_MISUSE} -do_test multiplex-1.10.8 { db close } {} -do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown } {SQLITE_OK} +do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.9.2 { sqlite3 db test.db } {} +do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK} +do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE} +do_test multiplex-1.9.5 { multiplex_set db main -1 16 } {SQLITE_MISUSE} +do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK} +do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_MISUSE} +do_test multiplex-1.9.8 { multiplex_set db main 1073741824 1 } {SQLITE_OK} +do_test multiplex-1.9.9 { db close } {} +do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} + +do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.10.2 { sqlite3 db test.db } {} +do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } } {SQLITE_OK} +do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } } {SQLITE_MISUSE} +do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } } {SQLITE_MISUSE} +do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } } {SQLITE_OK} +do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } } {SQLITE_MISUSE} +do_test multiplex-1.10.8 { execsql { SELECT multiplex_control(2, 1073741824); } } {SQLITE_OK} +do_test multiplex-1.10.9 { db close } {} +do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} + +do_test multiplex-1.11.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.11.2 { sqlite3 db test.db } {} +do_test multiplex-1.11.3 { sqlite3_multiplex_control db main enable 0 } {SQLITE_OK} +do_test multiplex-1.11.4 { sqlite3_multiplex_control db main enable 1 } {SQLITE_OK} +do_test multiplex-1.11.5 { sqlite3_multiplex_control db main enable -1 } {SQLITE_OK} +do_test multiplex-1.11.6 { db close } {} +do_test multiplex-1.11.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} + +do_test multiplex-1.12.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.12.2 { sqlite3 db test.db } {} +do_test multiplex-1.12.3 { execsql { SELECT multiplex_control(1, 0); } } {SQLITE_OK} +do_test multiplex-1.12.4 { execsql { SELECT multiplex_control(1, 1); } } {SQLITE_OK} +do_test multiplex-1.12.5 { execsql { SELECT multiplex_control(1, -1); } } {SQLITE_OK} +do_test multiplex-1.12.6 { db close } {} +do_test multiplex-1.12.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} #------------------------------------------------------------------------- # Some simple warm-body tests with a single database file in rollback @@ -104,7 +123,7 @@ do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown } {S # # multiplex-2.3.*: Open and close a second db. # -# multiplex-2.4.*: Try to shutdown the multiplex system befor e closing the db +# multiplex-2.4.*: Try to shutdown the multiplex system before closing the db # file. Check that this fails and the multiplex system still works # afterwards. Then close the database and successfully shut # down the multiplex system. @@ -113,6 +132,9 @@ do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown } {S # # multiplex-2.6.*: More reading/writing with varying small chunk sizes, as # well as varying journal mode. +# +# multiplex-2.7.*: Disable/enable tests. +# sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 @@ -261,6 +283,32 @@ foreach jmode $all_journal_modes { } } +do_test multiplex-2.7.1 { multiplex_delete test.db } {} +do_test multiplex-2.7.2 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-2.7.3 { sqlite3 db test.db } {} +do_test multiplex-2.7.4 { execsql { SELECT multiplex_control(2, 65536); } } {SQLITE_OK} +do_test multiplex-2.7.5 { execsql { SELECT multiplex_control(1, 0); } } {SQLITE_OK} +do_test multiplex-2.7.6 { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, randomblob(1000)); + } +} {} +# verify only one file, and file size is less than chunks size +do_test multiplex-2.7.7 { expr ([file size [multiplex_name test.db 0]] < 65536) } {1} +do_test multiplex-2.7.8 { file exists [multiplex_name test.db 1] } {0} +do_test multiplex-2.7.9 { + execsql { + INSERT INTO t1 VALUES(1, randomblob(65536)); + } +} {} +# verify only one file, and file size exceeds chunks size +do_test multiplex-2.7.10 { expr ([file size [multiplex_name test.db 0]] > 65536) } {1} +do_test multiplex-2.7.11 { file exists [multiplex_name test.db 1] } {0} +do_test multiplex-2.7.12 { db close } {} +do_test multiplex-2.7.13 { sqlite3_multiplex_shutdown } {SQLITE_OK} + + #------------------------------------------------------------------------- # Try some tests with more than one connection to a database file. Still # in rollback mode. From 3801b65d62a9d3f04c55988520aa700aab5cd00f Mon Sep 17 00:00:00 2001 From: shaneh Date: Fri, 1 Apr 2011 14:22:46 +0000 Subject: [PATCH 13/31] Removed dependency on sqliteInt.h so that multiplex VFS shim can be compiled as loadable module. FossilOrigin-Name: 718f1ad7df9115871ba6159012d3183183fc40a1 --- manifest | 16 ++++---- manifest.uuid | 2 +- src/test_multiplex.c | 97 +++++++++++++++++++++++++++++++------------- src/test_multiplex.h | 6 +-- test/multiplex.test | 68 +++++++++++++++++-------------- 5 files changed, 118 insertions(+), 71 deletions(-) diff --git a/manifest b/manifest index 43d10d3845..1e425354d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable/disable\ssupport. -D 2011-03-31T15:11:53.959 +C Removed\sdependency\son\ssqliteInt.h\sso\sthat\smultiplex\sVFS\sshim\scan\sbe\scompiled\sas\sloadable\smodule. +D 2011-04-01T14:22:46.544 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -209,8 +209,8 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d -F src/test_multiplex.c c0d9450b63b0f785795e4873ce90002414921a61 -F src/test_multiplex.h bf7b2d303688c32cdd1cee3ffdc377f13391e311 +F src/test_multiplex.c fdabd793ee7a9642c5a8a470def2347144c46d05 +F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c @@ -576,7 +576,7 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 -F test/multiplex.test 5373b2c3b0f3e262e746652d8f93b6f6297b15ba +F test/multiplex.test a88f3e2c16e567e72be7296195c59fbdd6a8d3d4 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723 @@ -914,7 +914,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P fee9734c193a8bec9599e02e16938179e642bf5e -R 9ef3873d6c48b9ead5e6ba118b2bc91f +P b3c6d9aa9e2124a2f2a1a5f9dbbd7db3b1d01a31 +R 5fdb22cfeb915ca0348434fc3aeb88a3 U shaneh -Z 53dc1c2b6709916c1194488b48f81a5e +Z c6a6d5930d83831b14cb5982ae50977b diff --git a/manifest.uuid b/manifest.uuid index 1ae76db767..6c14b08a21 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b3c6d9aa9e2124a2f2a1a5f9dbbd7db3b1d01a31 \ No newline at end of file +718f1ad7df9115871ba6159012d3183183fc40a1 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index a49825717e..d8a7db86e1 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -22,7 +22,6 @@ #include "sqlite3.h" #include #include -#include "sqliteInt.h" #include "test_multiplex.h" #ifndef SQLITE_CORE @@ -30,6 +29,16 @@ #endif #include "sqlite3ext.h" +/* +** These should be defined to be the same as the values in +** sqliteInt.h. They are defined seperately here so that +** the multiplex VFS shim can be built as a loadable +** module. +*/ +#define UNUSED_PARAMETER(x) (void)(x) +#define MAX_PAGE_SIZE 0x10000 +#define DEFAULT_SECTOR_SIZE 0x1000 + /* ** For a build without mutexes, no-op the mutex calls. */ @@ -50,9 +59,9 @@ /* This is the limit on the chunk size. It may be changed by calling ** the xFileControl() interface. It will be rounded up to a -** multiple of SQLITE_MAX_PAGE_SIZE. We default it here to 1GB. +** multiple of MAX_PAGE_SIZE. We default it here to 1GB. */ -#define SQLITE_MULTIPLEX_CHUNK_SIZE (SQLITE_MAX_PAGE_SIZE*16384) +#define SQLITE_MULTIPLEX_CHUNK_SIZE (MAX_PAGE_SIZE*16384) /* Default limit on number of chunks. Care should be taken ** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT @@ -168,6 +177,21 @@ static struct { static void multiplexEnter(void){ sqlite3_mutex_enter(gMultiplex.pMutex); } static void multiplexLeave(void){ sqlite3_mutex_leave(gMultiplex.pMutex); } +/* +** Compute a string length that is limited to what can be stored in +** lower 30 bits of a 32-bit signed integer. +** +** The value returned will never be negative. Nor will it ever be greater +** than the actual length of the string. For very long strings (greater +** than 1GiB) the value returned might be less than the true string length. +*/ +int multiplexStrlen30(const char *z){ + const char *z2 = z; + if( z==0 ) return 0; + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); +} + /* Translate an sqlite3_file* that is really a multiplexGroup* into ** the sqlite3_file* for the underlying original VFS. */ @@ -199,13 +223,14 @@ static sqlite3_file *multiplexSubOpen(multiplexConn *pConn, int iChunk, int *rc, return NULL; } +/* +** This is the implementation of the multiplex_control() SQL function. +*/ static void multiplexControlFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - extern const char *sqlite3TestErrorName(int); - extern int multiplexFileControl(sqlite3_file *, int, void *); int rc = SQLITE_OK; sqlite3 *db = sqlite3_context_db_handle(context); int op; @@ -229,18 +254,19 @@ static void multiplexControlFunc( op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; break; default: - rc = SQLITE_ERROR; + rc = SQLITE_NOTFOUND; break; } } if( rc==SQLITE_OK ){ rc = sqlite3_file_control(db, 0, op, &iVal); } - sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT); + sqlite3_result_error_code(context, rc); } /* -** This is the entry point to register the auto-extension for the multiplex_control() function. +** This is the entry point to register the auto-extension for the +** multiplex_control() function. */ static int multiplexFuncInit( sqlite3 *db, @@ -249,7 +275,7 @@ static int multiplexFuncInit( ){ int rc; rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, - 0, multiplexControlFunc, 0, 0); + 0, multiplexControlFunc, 0, 0); return rc; } @@ -274,7 +300,7 @@ static int multiplexOpen( multiplexGroup *pGroup; /* Corresponding multiplexGroup object */ sqlite3_file *pSubOpen; /* Real file descriptor */ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - int nName = sqlite3Strlen30(zName); + int nName = multiplexStrlen30(zName); int i; int sz; @@ -286,11 +312,11 @@ static int multiplexOpen( multiplexEnter(); pMultiplexOpen = (multiplexConn*)pConn; /* allocate space for group */ - sz = sizeof(multiplexGroup) /* multiplexGroup */ - + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */ - + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */ - + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */ - + nName + 1; /* zName */ + sz = sizeof(multiplexGroup) /* multiplexGroup */ + + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */ + + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */ + + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */ + + nName + 1; /* zName */ #ifndef SQLITE_MULTIPLEX_EXT_OVWR sz += SQLITE_MULTIPLEX_EXT_SZ; assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname); @@ -362,7 +388,7 @@ static int multiplexDelete( ){ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ int rc = SQLITE_OK; - int nName = sqlite3Strlen30(zName); + int nName = multiplexStrlen30(zName); int i; UNUSED_PARAMETER(pVfs); @@ -374,12 +400,17 @@ static int multiplexDelete( int exists = 0; if( i ){ #ifdef SQLITE_MULTIPLEX_EXT_OVWR - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+nName-SQLITE_MULTIPLEX_EXT_SZ, + SQLITE_MULTIPLEX_EXT_FMT, i); #else - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+nName, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+nName, + SQLITE_MULTIPLEX_EXT_FMT, i); #endif } - rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, + SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, delete it */ rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir); @@ -569,9 +600,13 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ pGroup->bOpen[i] = 0; } #ifdef SQLITE_MULTIPLEX_EXT_OVWR - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, + SQLITE_MULTIPLEX_EXT_FMT, i); #else - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+pGroup->nName, + SQLITE_MULTIPLEX_EXT_FMT, i); #endif rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0); if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE; @@ -634,12 +669,17 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1); if( i ){ #ifdef SQLITE_MULTIPLEX_EXT_OVWR - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, + SQLITE_MULTIPLEX_EXT_FMT, i); #else - sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, gMultiplex.zName+pGroup->nName, SQLITE_MULTIPLEX_EXT_FMT, i); + sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, + gMultiplex.zName+pGroup->nName, + SQLITE_MULTIPLEX_EXT_FMT, i); #endif } - rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, SQLITE_ACCESS_EXISTS, &exists); + rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, + SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, open it */ pSubOpen = multiplexSubOpen(p, i, &rc, NULL); @@ -728,9 +768,9 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ if( nChunkSize<1 ){ rc = SQLITE_MISUSE; }else{ - /* Round up to nearest multiple of SQLITE_MAX_PAGE_SIZE. */ - nChunkSize = (nChunkSize + (SQLITE_MAX_PAGE_SIZE-1)); - nChunkSize &= ~(SQLITE_MAX_PAGE_SIZE-1); + /* Round up to nearest multiple of MAX_PAGE_SIZE. */ + nChunkSize = (nChunkSize + (MAX_PAGE_SIZE-1)); + nChunkSize &= ~(MAX_PAGE_SIZE-1); pGroup->nChunkSize = nChunkSize; rc = SQLITE_OK; } @@ -771,7 +811,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){ if( pSubOpen ){ return pSubOpen->pMethods->xSectorSize(pSubOpen); } - return SQLITE_DEFAULT_SECTOR_SIZE; + return DEFAULT_SECTOR_SIZE; } /* Pass xDeviceCharacteristics requests through to the original VFS unchanged. @@ -941,6 +981,7 @@ int sqlite3_multiplex_shutdown(void){ /***************************** Test Code ***********************************/ #ifdef SQLITE_TEST #include +extern const char *sqlite3TestErrorName(int); /* diff --git a/src/test_multiplex.h b/src/test_multiplex.h index 1a574c1a87..ec1ba9bb21 100644 --- a/src/test_multiplex.h +++ b/src/test_multiplex.h @@ -60,16 +60,16 @@ ** function gives access to the xFileControl interface of the ** multiplex VFS shim. ** -** SELECT multiplex_control(,) ; +** SELECT multiplex_control(,); ** ** =1 MULTIPLEX_CTRL_ENABLE ** =0 disable ** =1 enable ** -** =1 MULTIPLEX_CTRL_SET_CHUNK_SIZE +** =2 MULTIPLEX_CTRL_SET_CHUNK_SIZE ** int, chunk size ** -** =1 MULTIPLEX_CTRL_SET_MAX_CHUNKS +** =3 MULTIPLEX_CTRL_SET_MAX_CHUNKS ** int, max chunks ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once diff --git a/test/multiplex.test b/test/multiplex.test index c76cee71a0..518cbe37a0 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -86,32 +86,39 @@ do_test multiplex-1.9.8 { multiplex_set db main 1073741824 1 } {SQLITE_OK} do_test multiplex-1.9.9 { db close } {} do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.10.2 { sqlite3 db test.db } {} -do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } } {SQLITE_OK} -do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } } {SQLITE_MISUSE} -do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } } {SQLITE_MISUSE} -do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } } {SQLITE_OK} -do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } } {SQLITE_MISUSE} -do_test multiplex-1.10.8 { execsql { SELECT multiplex_control(2, 1073741824); } } {SQLITE_OK} -do_test multiplex-1.10.9 { db close } {} -do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} +do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.10.2 { sqlite3 db test.db } {} +do_test multiplex-1.10.3 { lindex [ catchsql { SELECT multiplex_control(2, 32768); } ] 0 } {0} +do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {1} +do_test multiplex-1.10.5 { lindex [ catchsql { SELECT multiplex_control(2, -1); } ] 0 } {1} +do_test multiplex-1.10.6 { lindex [ catchsql { SELECT multiplex_control(2, 31); } ] 0 } {0} +do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {1} +do_test multiplex-1.10.8 { lindex [ catchsql { SELECT multiplex_control(2, 1073741824); } ] 0 } {0} +do_test multiplex-1.10.9 { db close } {} +do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.11.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.11.2 { sqlite3 db test.db } {} -do_test multiplex-1.11.3 { sqlite3_multiplex_control db main enable 0 } {SQLITE_OK} -do_test multiplex-1.11.4 { sqlite3_multiplex_control db main enable 1 } {SQLITE_OK} -do_test multiplex-1.11.5 { sqlite3_multiplex_control db main enable -1 } {SQLITE_OK} -do_test multiplex-1.11.6 { db close } {} -do_test multiplex-1.11.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} +do_test multiplex-1.11.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.11.2 { sqlite3 db test.db } {} +do_test multiplex-1.11.3 { sqlite3_multiplex_control db main enable 0 } {SQLITE_OK} +do_test multiplex-1.11.4 { sqlite3_multiplex_control db main enable 1 } {SQLITE_OK} +do_test multiplex-1.11.5 { sqlite3_multiplex_control db main enable -1 } {SQLITE_OK} +do_test multiplex-1.11.6 { db close } {} +do_test multiplex-1.11.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} -do_test multiplex-1.12.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-1.12.2 { sqlite3 db test.db } {} -do_test multiplex-1.12.3 { execsql { SELECT multiplex_control(1, 0); } } {SQLITE_OK} -do_test multiplex-1.12.4 { execsql { SELECT multiplex_control(1, 1); } } {SQLITE_OK} -do_test multiplex-1.12.5 { execsql { SELECT multiplex_control(1, -1); } } {SQLITE_OK} -do_test multiplex-1.12.6 { db close } {} -do_test multiplex-1.12.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} +do_test multiplex-1.12.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.12.2 { sqlite3 db test.db } {} +do_test multiplex-1.12.3 { lindex [ catchsql { SELECT multiplex_control(1, 0); } ] 0 } {0} +do_test multiplex-1.12.4 { lindex [ catchsql { SELECT multiplex_control(1, 1); } ] 0 } {0} +do_test multiplex-1.12.5 { lindex [ catchsql { SELECT multiplex_control(1, -1); } ] 0 } {0} +do_test multiplex-1.12.6 { db close } {} +do_test multiplex-1.12.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} + +do_test multiplex-1.13.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-1.13.2 { sqlite3 db test.db } {} +do_test multiplex-1.13.3 { lindex [ catchsql { SELECT multiplex_control(-1, 0); } ] 0 } {1} +do_test multiplex-1.13.4 { lindex [ catchsql { SELECT multiplex_control(4, 1); } ] 0 } {1} +do_test multiplex-1.13.6 { db close } {} +do_test multiplex-1.13.7 { sqlite3_multiplex_shutdown } {SQLITE_OK} #------------------------------------------------------------------------- # Some simple warm-body tests with a single database file in rollback @@ -283,11 +290,11 @@ foreach jmode $all_journal_modes { } } -do_test multiplex-2.7.1 { multiplex_delete test.db } {} -do_test multiplex-2.7.2 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} -do_test multiplex-2.7.3 { sqlite3 db test.db } {} -do_test multiplex-2.7.4 { execsql { SELECT multiplex_control(2, 65536); } } {SQLITE_OK} -do_test multiplex-2.7.5 { execsql { SELECT multiplex_control(1, 0); } } {SQLITE_OK} +do_test multiplex-2.7.1 { multiplex_delete test.db } {} +do_test multiplex-2.7.2 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} +do_test multiplex-2.7.3 { sqlite3 db test.db } {} +do_test multiplex-2.7.4 { lindex [ catchsql { SELECT multiplex_control(2, 65536); } ] 0 } {0} +do_test multiplex-2.7.5 { lindex [ catchsql { SELECT multiplex_control(1, 0); } ] 0 } {0} do_test multiplex-2.7.6 { execsql { CREATE TABLE t1(a PRIMARY KEY, b); @@ -299,7 +306,7 @@ do_test multiplex-2.7.7 { expr ([file size [multiplex_name test.db 0]] < 65536) do_test multiplex-2.7.8 { file exists [multiplex_name test.db 1] } {0} do_test multiplex-2.7.9 { execsql { - INSERT INTO t1 VALUES(1, randomblob(65536)); + INSERT INTO t1 VALUES(2, randomblob(65536)); } } {} # verify only one file, and file size exceeds chunks size @@ -308,7 +315,6 @@ do_test multiplex-2.7.11 { file exists [multiplex_name test.db 1] } do_test multiplex-2.7.12 { db close } {} do_test multiplex-2.7.13 { sqlite3_multiplex_shutdown } {SQLITE_OK} - #------------------------------------------------------------------------- # Try some tests with more than one connection to a database file. Still # in rollback mode. From f18749542f4a5e535ccb43cf82ea6beda7418599 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 1 Apr 2011 16:50:07 +0000 Subject: [PATCH 14/31] When simulating an error in the close() system call, close the file descriptor anyway. Otherwise long running tests leak too many file-descriptors and crash. FossilOrigin-Name: 81ddbf43366c18ebdd46558d6a0fbee2ce6a4c4e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test_syscall.c | 6 ++++++ tool/mkopts.tcl | 0 4 files changed, 14 insertions(+), 8 deletions(-) mode change 100755 => 100644 tool/mkopts.tcl diff --git a/manifest b/manifest index 179b8e01d2..dcaa2e9d59 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sit\sis\snot\spossible\sto\sadd\sa\scolumn\sto\sa\ssystem\stable\susing\sALTER\sTABLE. -D 2011-04-01T15:15:58.380 +C When\ssimulating\san\serror\sin\sthe\sclose()\ssystem\scall,\sclose\sthe\sfile\sdescriptor\sanyway.\sOtherwise\slong\srunning\stests\sleak\stoo\smany\sfile-descriptors\sand\scrash. +D 2011-04-01T16:50:07 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -220,7 +220,7 @@ F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6 F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd -F src/test_syscall.c 349a2b913e82b029f01527f58f65d66a02a09a84 +F src/test_syscall.c 61bb14684142a19c580a13b4dde680044d37e0f5 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0 F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86 @@ -896,7 +896,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 7e237aea22084416d02b89d5223de4e1ca76882d -R 68179f8f20bd7e83c0daf30e8b4b7cff +P d9707ef8dcd29667b6d366897f6ad02c87aa0041 +R 61773a6586c7ffae758339f441c619af U dan -Z 07da6539f8d6e81dde928bab49d2b3fe +Z 4a1b718c29bc9f24adfbad40e4254b98 diff --git a/manifest.uuid b/manifest.uuid index e4175092fa..6f0caefd4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9707ef8dcd29667b6d366897f6ad02c87aa0041 \ No newline at end of file +81ddbf43366c18ebdd46558d6a0fbee2ce6a4c4e \ No newline at end of file diff --git a/src/test_syscall.c b/src/test_syscall.c index dbac01d69b..a757e66a5a 100644 --- a/src/test_syscall.c +++ b/src/test_syscall.c @@ -214,6 +214,12 @@ static int ts_open(const char *zFile, int flags, int mode){ */ static int ts_close(int fd){ if( tsIsFail() ){ + /* Even if simulating an error, close the original file-descriptor. + ** This is to stop the test process from running out of file-descriptors + ** when running a long test. If a call to close() appears to fail, SQLite + ** never attempts to use the file-descriptor afterwards (or even to close + ** it a second time). */ + orig_close(fd); return -1; } return orig_close(fd); diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 From e433235ec237ecfc8e3d9b96114a9e8ad980408d Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 1 Apr 2011 17:53:19 +0000 Subject: [PATCH 15/31] Change analyze7.test so that it works without SQLITE_ENABLE_STAT2 defined. FossilOrigin-Name: 9415201c8a0b9b640f5997c5348c5df812e88230 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/analyze7.test | 19 ++++++++++++++++--- tool/mkopts.tcl | 0 4 files changed, 24 insertions(+), 11 deletions(-) mode change 100644 => 100755 tool/mkopts.tcl diff --git a/manifest b/manifest index dcaa2e9d59..5404553284 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\ssimulating\san\serror\sin\sthe\sclose()\ssystem\scall,\sclose\sthe\sfile\sdescriptor\sanyway.\sOtherwise\slong\srunning\stests\sleak\stoo\smany\sfile-descriptors\sand\scrash. -D 2011-04-01T16:50:07 +C Change\sanalyze7.test\sso\sthat\sit\sworks\swithout\sSQLITE_ENABLE_STAT2\sdefined. +D 2011-04-01T17:53:20 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -259,7 +259,7 @@ F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290 -F test/analyze7.test 06405dd3d2a3101de14270da508016a59254873b +F test/analyze7.test 8095fed183e1fb999c1b1c4a1606cec1bcb13d1f F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e @@ -896,7 +896,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -921,7 +921,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d9707ef8dcd29667b6d366897f6ad02c87aa0041 -R 61773a6586c7ffae758339f441c619af +P 81ddbf43366c18ebdd46558d6a0fbee2ce6a4c4e +R 99f8eb376089a9fabbaf964c125c721f U dan -Z 4a1b718c29bc9f24adfbad40e4254b98 +Z bf935093daa7a73e12043061e537a56c diff --git a/manifest.uuid b/manifest.uuid index 6f0caefd4a..bd021d3020 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -81ddbf43366c18ebdd46558d6a0fbee2ce6a4c4e \ No newline at end of file +9415201c8a0b9b640f5997c5348c5df812e88230 \ No newline at end of file diff --git a/test/analyze7.test b/test/analyze7.test index 4c2fd53e85..9107376e28 100644 --- a/test/analyze7.test +++ b/test/analyze7.test @@ -87,9 +87,22 @@ do_test analyze7-3.0 { do_test analyze7-3.1 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~10 rows)}} -do_test analyze7-3.2 { - execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} -} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~102 rows)}} +do_test analyze7-3.2.1 { + execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;} +} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~86 rows)}} +ifcapable stat2 { + # If ENABLE_STAT2 is defined, SQLite comes up with a different estimated + # row count for (c=2) than it does for (c=?). + do_test analyze7-3.2.2 { + execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} + } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~102 rows)}} +} else { + # If ENABLE_STAT2 is not defined, the expected row count for (c=2) is the + # same as that for (c=?). + do_test analyze7-3.2.3 { + execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;} + } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~86 rows)}} +} do_test analyze7-3.3 { execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}} diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755 From 1d21021f59ce16c4e4d10fc314c9fa3300fc04b2 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2011 18:12:58 +0000 Subject: [PATCH 16/31] Add a script that will break the amalgamation source file up into 4 or 5 smaller source files, each 32K lines or fewer, and a single "sqlite3-all.c" source file that #includes the others. FossilOrigin-Name: 5d34e64d4d2398aa9a54fd0a4f1de37ced7ea5dd --- manifest | 17 +++++---- manifest.uuid | 2 +- tool/mkopts.tcl | 0 tool/mksqlite3c.tcl | 2 +- tool/split-sqlite3c.tcl | 82 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 10 deletions(-) mode change 100755 => 100644 tool/mkopts.tcl create mode 100644 tool/split-sqlite3c.tcl diff --git a/manifest b/manifest index 5404553284..28f120574c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sanalyze7.test\sso\sthat\sit\sworks\swithout\sSQLITE_ENABLE_STAT2\sdefined. -D 2011-04-01T17:53:20 +C Add\sa\sscript\sthat\swill\sbreak\sthe\samalgamation\ssource\sfile\sup\sinto\s4\sor\s5\nsmaller\ssource\sfiles,\seach\s32K\slines\sor\sfewer,\sand\sa\ssingle\s"sqlite3-all.c"\nsource\sfile\sthat\s#includes\sthe\sothers. +D 2011-04-01T18:12:58.662 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -896,9 +896,9 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 -F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 +F tool/mksqlite3c.tcl 623e26cc8c83322e4151d3ad85ac69d41221bae8 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87 F tool/omittest.tcl 4f4cc66bb7ca6a5b8f61ee37b6333f60fb8a746a @@ -920,8 +920,9 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e +F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 81ddbf43366c18ebdd46558d6a0fbee2ce6a4c4e -R 99f8eb376089a9fabbaf964c125c721f -U dan -Z bf935093daa7a73e12043061e537a56c +P 9415201c8a0b9b640f5997c5348c5df812e88230 +R c3ff07e6303499e88c2cf0a9abaa71e9 +U drh +Z 975ba0a508eed8e252cfd7014026f442 diff --git a/manifest.uuid b/manifest.uuid index bd021d3020..8128966455 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9415201c8a0b9b640f5997c5348c5df812e88230 \ No newline at end of file +5d34e64d4d2398aa9a54fd0a4f1de37ced7ea5dd \ No newline at end of file diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index d56b06dbc9..fa99f2df7b 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -51,7 +51,7 @@ puts $out [subst \ {/****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version $VERSION. By combining all the individual C code files into this -** single large file, the entire code can be compiled as a one translation +** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single diff --git a/tool/split-sqlite3c.tcl b/tool/split-sqlite3c.tcl new file mode 100644 index 0000000000..287b752828 --- /dev/null +++ b/tool/split-sqlite3c.tcl @@ -0,0 +1,82 @@ +#!/usr/bin/tclsh +# +# This script splits the sqlite3.c amalgamated source code files into +# several smaller files such that no single files is more than a fixed +# number of lines in length (32k or 64k). Each of the split out files +# is #include-ed by the master file. +# +# Splitting files up this way allows them to be used with older compilers +# that cannot handle really long source files. +# +set MAX 32768 ;# Maximum number of lines per file. + +set BEGIN {^/\*+ Begin file ([a-zA-Z0-9_.]+) \*+/} +set END {^/\*+ End of %s \*+/} + +set in [open sqlite3.c] +set out1 [open sqlite3-all.c w] + +# Copy the header from sqlite3.c into sqlite3-all.c +# +while {[gets $in line]} { + if {[regexp $BEGIN $line]} break + puts $out1 $line +} + +# Gather the complete content of a file into memory. Store the +# content in $bufout. Store the number of lines is $nout +# +proc gather_one_file {firstline bufout nout} { + regexp $::BEGIN $firstline all filename + set end [format $::END $filename] + upvar $bufout buf $nout n + set buf $firstline\n + global in + set n 0 + while {[gets $in line]>=0} { + incr n + append buf $line\n + if {[regexp $end $line]} break + } +} + +# Write a big chunk of text in to an auxiliary file "sqlite3-NNN.c". +# Also add an appropriate #include to sqlite3-all.c +# +set filecnt 0 +proc write_one_file {content} { + global filecnt + incr filecnt + set out [open sqlite3-$filecnt.c w] + puts -nonewline $out $content + close $out + puts $::out1 "#include \"sqlite3-$filecnt.c\"" +} + +# Continue reading input. Store chunks in separate files and add +# the #includes to the main sqlite3-all.c file as necessary to reference +# the extra chunks. +# +set all {} +set N 0 +while {[regexp $BEGIN $line]} { + set buf {} + set n 0 + gather_one_file $line buf n + if {$n+$N>=$MAX} { + write_one_file $all + set all {} + set N 0 + } + append all $buf + incr N $n + while {[gets $in line]>=0} { + if {[regexp $BEGIN $line]} break + puts $out1 $line + } +} +if {$N>0} { + write_one_file $all +} +close $out1 +close $in From 7fa65fbfa8f641a3125c928fdc2d4dda1be4d9e0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 1 Apr 2011 19:14:40 +0000 Subject: [PATCH 17/31] Changes to wal tests so that they work with DEFAULT_AUTOVACUUM defined. FossilOrigin-Name: b477852f82c1fddbda61fad83d55055ad8503dda --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- test/wal.test | 1 + test/wal2.test | 4 ++++ test/wal3.test | 3 +++ test/wal5.test | 3 +++ 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 6d5245d343..5eb9a43527 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\smultiplexer\senhancements\sback\sinto\sthe\strunk. -D 2011-04-01T18:39:24.584 +C Changes\sto\swal\stests\sso\sthat\sthey\swork\swith\sDEFAULT_AUTOVACUUM\sdefined. +D 2011-04-01T19:14:40.912 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -857,11 +857,11 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d -F test/wal.test f060cae4b2164c4375109a8f803873187234661d -F test/wal2.test 57a218446654ed3e3592c925762633c1d1e85636 -F test/wal3.test ec87d9dd9e9cebabed4024064e8ff531d336ead2 +F test/wal.test 973a4747a69247a43cc03292c44f59cc76f4df65 +F test/wal2.test e561a8c6fdd1c2cd1876f3e39757934e7b7361f8 +F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30 -F test/wal5.test 3fef990d256cd9e95e9ad97e5dfdf3f150743fce +F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8 F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4 @@ -923,7 +923,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 5d34e64d4d2398aa9a54fd0a4f1de37ced7ea5dd 718f1ad7df9115871ba6159012d3183183fc40a1 -R 3be437ca6e714e1f6c593836a791944c -U drh -Z e8e2d5336305d42bc1912c6d6b830ecf +P 2c125710cbf04198464d436b16e5ef37c5b219cf +R b73fd492db86ba17fd0ee03f6edbe84f +U dan +Z 514a0a4f4cb96eef649ff183f226e66c diff --git a/manifest.uuid b/manifest.uuid index 57e66f8f57..3e81723377 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2c125710cbf04198464d436b16e5ef37c5b219cf \ No newline at end of file +b477852f82c1fddbda61fad83d55055ad8503dda \ No newline at end of file diff --git a/test/wal.test b/test/wal.test index 339661e2ee..257a87b092 100644 --- a/test/wal.test +++ b/test/wal.test @@ -463,6 +463,7 @@ do_multiclient_test tn { # do_test wal-10.$tn.1 { execsql { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); diff --git a/test/wal2.test b/test/wal2.test index 7bb820cc1b..82234330fa 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -343,6 +343,7 @@ file delete -force test.db test.db-wal test.db-journal do_test wal2-4.1 { sqlite3 db test.db execsql { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; CREATE TABLE data(x); INSERT INTO data VALUES('need xShmOpen to see this'); @@ -622,6 +623,7 @@ set READMARK1_WRITE { foreach {tn sql res expected_locks} { 2 { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; BEGIN; CREATE TABLE t1(x); @@ -707,6 +709,7 @@ tvfs delete do_test wal2-6.5.1 { sqlite3 db test.db execsql { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = wal; PRAGMA locking_mode = exclusive; CREATE TABLE t2(a, b); @@ -1166,6 +1169,7 @@ foreach {tn sql reslist} { } { faultsim_delete_and_reopen + execsql {PRAGMA auto_vacuum = 0} execsql $sql do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal} diff --git a/test/wal3.test b/test/wal3.test index b006638937..bd296154e0 100644 --- a/test/wal3.test +++ b/test/wal3.test @@ -413,6 +413,7 @@ testvfs T -default 1 do_test wal3-6.1.1 { file delete -force test.db test.db-journal test.db wal sqlite3 db test.db + execsql { PRAGMA auto_vacuum = off } execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE t1(a, b); @@ -494,6 +495,7 @@ do_test wal3-6.2.1 { file delete -force test.db test.db-journal test.db wal sqlite3 db test.db sqlite3 db2 test.db + execsql { PRAGMA auto_vacuum = off } execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE t1(a, b); @@ -617,6 +619,7 @@ do_test wal3-8.1 { sqlite3 db test.db sqlite3 db2 test.db execsql { + PRAGMA auto_vacuum = off; PRAGMA journal_mode = WAL; CREATE TABLE b(c); INSERT INTO b VALUES('Tehran'); diff --git a/test/wal5.test b/test/wal5.test index d571dae0d1..ad6bcfc7d8 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -169,6 +169,8 @@ foreach {testprefix do_wal_checkpoint} { sql2 { ATTACH 'test.db2' AS aux } sql3 { ATTACH 'test.db2' AS aux } sql1 { + PRAGMA aux.auto_vacuum = 0; + PRAGMA main.auto_vacuum = 0; PRAGMA main.page_size=1024; PRAGMA main.journal_mode=WAL; PRAGMA aux.page_size=1024; PRAGMA aux.journal_mode=WAL; } @@ -309,6 +311,7 @@ foreach {testprefix do_wal_checkpoint} { do_test 3.$tn.1 { sql1 { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; PRAGMA synchronous = normal; CREATE TABLE t1(x, y); From 1b05c423fe293c13fad8f63699458433c60c8009 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2011 20:28:31 +0000 Subject: [PATCH 18/31] Add additional test data and documentation to the fuzzer virtual table. FossilOrigin-Name: a6a81d4fdafabba514e8f8e1958d6132b3850772 --- manifest | 16 +- manifest.uuid | 2 +- src/test_fuzzer.c | 81 +++ test/fuzzer1.test | 1335 +++++++++++++++++++++++++++++++++++++++++++++ tool/mkopts.tcl | 0 5 files changed, 1425 insertions(+), 9 deletions(-) mode change 100755 => 100644 tool/mkopts.tcl diff --git a/manifest b/manifest index 7aec386c02..a081a12fe5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sto\san\sO(NlogN)\salgorithm\sfor\sthe\spriority\squeue.\s\sAn\sinsertion\ssort\nwas\sway\stoo\sslow. -D 2011-03-30T01:43:00.780 +C Add\sadditional\stest\sdata\sand\sdocumentation\sto\sthe\sfuzzer\svirtual\stable. +D 2011-04-01T20:28:31.337 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -202,7 +202,7 @@ F src/test_config.c 62f0f8f934b1d5c7e4cd4f506ae453a1117b47d7 F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5 -F src/test_fuzzer.c edc2aaa0f75ce49efef39bcd2df45138479b0992 +F src/test_fuzzer.c f884f6f32e8513d34248d6e1ac8a32047fead254 F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2 F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -476,7 +476,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c -F test/fuzzer1.test a81a50d7ba6005d9cc98bf58b8aae8c3e73e11a6 +F test/fuzzer1.test 3105b5a89a6cb0d475f0877debec942fe4143462 F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d @@ -893,7 +893,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309 -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x +F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff @@ -918,7 +918,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2cf4158ff051916717fc2c0f4b6332d5f6ea6e3d -R 9250685bf3b3b21491f862d4fc8952d0 +P 7958cbba736a599c1293b06602eec43dfe4fd7d1 +R a5f7c9b6891187773247bee84f644851 U drh -Z 0b9911f371ac67382b47460caefb0a30 +Z b39064b9fd85dd1a63e76912c214c45c diff --git a/manifest.uuid b/manifest.uuid index dfc8e61028..f8b467bbd6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7958cbba736a599c1293b06602eec43dfe4fd7d1 \ No newline at end of file +a6a81d4fdafabba514e8f8e1958d6132b3850772 \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index ffdd61c9f6..cf59257175 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -12,6 +12,87 @@ ** ** Code for demonstartion virtual table that generates variations ** on an input word at increasing edit distances from the original. +** +** A fuzzer virtual table is created like this: +** +** CREATE VIRTUAL TABLE temp.f USING fuzzer; +** +** The name of the new virtual table in the example above is "f". +** Note that all fuzzer virtual tables must be TEMP tables. The +** "temp." prefix in front of the table name is required when the +** table is being created. The "temp." prefix can be omitted when +** using the table as long as the name is unambiguous. +** +** Before being used, the fuzzer needs to be programmed by giving it +** character transformations and a cost associated with each transformation. +** Examples: +** +** INSERT INTO f(cFrom,cTo,Cost) VALUES('','a',100); +** +** The above statement says that the cost of inserting a letter 'a' is +** 100. (All costs are integers. We recommend that costs be scaled so +** that the average cost is around 100.) +** +** INSERT INTO f(cFrom,cTo,Cost) VALUES('b','',87); +** +** The above statement says that the cost of deleting a single letter +** 'b' is 87. +** +** INSERT INTO f(cFrom,cTo,Cost) VALUES('o','oe',38); +** INSERT INTO f(cFrom,cTo,Cost) VALUES('oe','o',40); +** +** This third example says that the cost of transforming the single +** letter "o" into the two-letter sequence "oe" is 38 and that the +** cost of transforming "oe" back into "o" is 40. +** +** After all the transformation costs have been set, the fuzzer table +** can be queried as follows: +** +** SELECT word, distance FROM f +** WHERE word MATCH 'abcdefg' +** AND distance<200; +** +** This first query outputs the string "abcdefg" and all strings that +** can be derived from that string by appling the specified transformations. +** The strings are output together with their total transformation cost +** (called "distance") and appear in order of increasing cost. No string +** is output more than once. If there are multiple ways to transform the +** target string into the output string then the lowest cost transform is +** the one that is returned. In the example, the search is limited to +** strings with a total distance of less than 200. +** +** It is important to put some kind of a limit on the fuzzer output. This +** can be either in the form of a LIMIT clause at the end of the query, +** or better, a "distance diff --git a/test/fuzzer1.test b/test/fuzzer1.test index 895d6b3b2a..d0575d2d00 100644 --- a/test/fuzzer1.test +++ b/test/fuzzer1.test @@ -43,5 +43,1340 @@ do_test fuzzer1-1.3 { } } {abcde 0 abcda 1 ebcde 10 ebcda 11 abcdo 100 ebcdo 110 obcde 110 obcda 111 obcdo 210} +do_test fuzzer1-2.0 { + execsql { + CREATE VIRTUAL TABLE temp.f2 USING fuzzer; + -- costs based on English letter frequencies + INSERT INTO f2(cFrom,cTo,cost) VALUES('a','e',24); + INSERT INTO f2(cFrom,cTo,cost) VALUES('a','o',47); + INSERT INTO f2(cFrom,cTo,cost) VALUES('a','u',50); + INSERT INTO f2(cFrom,cTo,cost) VALUES('e','a',23); + INSERT INTO f2(cFrom,cTo,cost) VALUES('e','i',33); + INSERT INTO f2(cFrom,cTo,cost) VALUES('e','o',37); + INSERT INTO f2(cFrom,cTo,cost) VALUES('i','e',33); + INSERT INTO f2(cFrom,cTo,cost) VALUES('i','y',33); + INSERT INTO f2(cFrom,cTo,cost) VALUES('o','a',41); + INSERT INTO f2(cFrom,cTo,cost) VALUES('o','e',46); + INSERT INTO f2(cFrom,cTo,cost) VALUES('o','u',57); + INSERT INTO f2(cFrom,cTo,cost) VALUES('u','o',58); + INSERT INTO f2(cFrom,cTo,cost) VALUES('y','i',33); + + INSERT INTO f2(cFrom,cTo,cost) VALUES('t','th',70); + INSERT INTO f2(cFrom,cTo,cost) VALUES('th','t',66); + + + INSERT INTO f2(cFrom,cTo,cost) VALUES('a','',84); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','b',106); + INSERT INTO f2(cFrom,cTo,cost) VALUES('b','',106); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','c',94); + INSERT INTO f2(cFrom,cTo,cost) VALUES('c','',94); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','d',89); + INSERT INTO f2(cFrom,cTo,cost) VALUES('d','',89); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','e',83); + INSERT INTO f2(cFrom,cTo,cost) VALUES('e','',83); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','f',97); + INSERT INTO f2(cFrom,cTo,cost) VALUES('f','',97); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','g',99); + INSERT INTO f2(cFrom,cTo,cost) VALUES('g','',99); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','h',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('h','',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','i',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('i','',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','j',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('j','',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','k',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('k','',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','l',89); + INSERT INTO f2(cFrom,cTo,cost) VALUES('l','',89); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','m',96); + INSERT INTO f2(cFrom,cTo,cost) VALUES('m','',96); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','n',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('n','',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','o',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('o','',85); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','p',100); + INSERT INTO f2(cFrom,cTo,cost) VALUES('p','',100); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','q',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('q','',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','r',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('r','',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','s',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('s','',86); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','t',84); + INSERT INTO f2(cFrom,cTo,cost) VALUES('t','',84); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','u',94); + INSERT INTO f2(cFrom,cTo,cost) VALUES('u','',94); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','v',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('v','',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','w',96); + INSERT INTO f2(cFrom,cTo,cost) VALUES('w','',96); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','x',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('x','',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','y',100); + INSERT INTO f2(cFrom,cTo,cost) VALUES('y','',100); + INSERT INTO f2(cFrom,cTo,cost) VALUES('','z',120); + INSERT INTO f2(cFrom,cTo,cost) VALUES('z','',120); + + -- Street names for the 28269 ZIPCODE. + -- + CREATE TEMP TABLE streetname(n TEXT UNIQUE); + INSERT INTO streetname VALUES('abbotsinch'); + INSERT INTO streetname VALUES('abbottsgate'); + INSERT INTO streetname VALUES('abbywood'); + INSERT INTO streetname VALUES('abner'); + INSERT INTO streetname VALUES('acacia ridge'); + INSERT INTO streetname VALUES('acorn creek'); + INSERT INTO streetname VALUES('acorn forest'); + INSERT INTO streetname VALUES('adel'); + INSERT INTO streetname VALUES('ainslie'); + INSERT INTO streetname VALUES('airways'); + INSERT INTO streetname VALUES('alabaster'); + INSERT INTO streetname VALUES('alba'); + INSERT INTO streetname VALUES('albertine'); + INSERT INTO streetname VALUES('alden glen'); + INSERT INTO streetname VALUES('alderson'); + INSERT INTO streetname VALUES('allen'); + INSERT INTO streetname VALUES('allen a brown'); + INSERT INTO streetname VALUES('allness glen'); + INSERT INTO streetname VALUES('aloysia'); + INSERT INTO streetname VALUES('alpine'); + INSERT INTO streetname VALUES('alwyn'); + INSERT INTO streetname VALUES('amaranthus'); + INSERT INTO streetname VALUES('amber glen'); + INSERT INTO streetname VALUES('amber leigh way'); + INSERT INTO streetname VALUES('amber meadows'); + INSERT INTO streetname VALUES('amberway'); + INSERT INTO streetname VALUES('ame'); + INSERT INTO streetname VALUES('amesbury hill'); + INSERT INTO streetname VALUES('anderson'); + INSERT INTO streetname VALUES('andrew thomas'); + INSERT INTO streetname VALUES('anduin falls'); + INSERT INTO streetname VALUES('ankeny'); + INSERT INTO streetname VALUES('annandale'); + INSERT INTO streetname VALUES('annbick'); + INSERT INTO streetname VALUES('antelope'); + INSERT INTO streetname VALUES('anzack'); + INSERT INTO streetname VALUES('apple glen'); + INSERT INTO streetname VALUES('applevalley'); + INSERT INTO streetname VALUES('appley mead'); + INSERT INTO streetname VALUES('aragorn'); + INSERT INTO streetname VALUES('arbor creek'); + INSERT INTO streetname VALUES('arbor day'); + INSERT INTO streetname VALUES('arbor meadows'); + INSERT INTO streetname VALUES('arbor spring'); + INSERT INTO streetname VALUES('arborview'); + INSERT INTO streetname VALUES('arklow'); + INSERT INTO streetname VALUES('armitage'); + INSERT INTO streetname VALUES('arvin'); + INSERT INTO streetname VALUES('ash cove'); + INSERT INTO streetname VALUES('ashford leigh'); + INSERT INTO streetname VALUES('ashmont'); + INSERT INTO streetname VALUES('atlas'); + INSERT INTO streetname VALUES('atwater'); + INSERT INTO streetname VALUES('auburn hill'); + INSERT INTO streetname VALUES('aulton link'); + INSERT INTO streetname VALUES('austin dekota'); + INSERT INTO streetname VALUES('austin knoll'); + INSERT INTO streetname VALUES('auten'); + INSERT INTO streetname VALUES('autumn harvest'); + INSERT INTO streetname VALUES('autumn oak'); + INSERT INTO streetname VALUES('autumn ridge'); + INSERT INTO streetname VALUES('avalon forest'); + INSERT INTO streetname VALUES('avalon loop'); + INSERT INTO streetname VALUES('avon farm'); + INSERT INTO streetname VALUES('avonhurst'); + INSERT INTO streetname VALUES('avonlea'); + INSERT INTO streetname VALUES('aynrand'); + INSERT INTO streetname VALUES('azure valley'); + INSERT INTO streetname VALUES('baberton'); + INSERT INTO streetname VALUES('baffin'); + INSERT INTO streetname VALUES('baggins'); + INSERT INTO streetname VALUES('balata'); + INSERT INTO streetname VALUES('ballantray'); + INSERT INTO streetname VALUES('ballston'); + INSERT INTO streetname VALUES('balsam tree'); + INSERT INTO streetname VALUES('bambi'); + INSERT INTO streetname VALUES('banwell'); + INSERT INTO streetname VALUES('barbee'); + INSERT INTO streetname VALUES('barefoot forest'); + INSERT INTO streetname VALUES('barnview'); + INSERT INTO streetname VALUES('baroda'); + INSERT INTO streetname VALUES('barson'); + INSERT INTO streetname VALUES('baskerville'); + INSERT INTO streetname VALUES('battle creek'); + INSERT INTO streetname VALUES('baucom'); + INSERT INTO streetname VALUES('bay pines'); + INSERT INTO streetname VALUES('beaker'); + INSERT INTO streetname VALUES('beard'); + INSERT INTO streetname VALUES('beardsley'); + INSERT INTO streetname VALUES('bearoak'); + INSERT INTO streetname VALUES('beauvista'); + INSERT INTO streetname VALUES('beaver creek'); + INSERT INTO streetname VALUES('beaver hollow'); + INSERT INTO streetname VALUES('bedlington'); + INSERT INTO streetname VALUES('beech cove'); + INSERT INTO streetname VALUES('beech crest'); + INSERT INTO streetname VALUES('beith'); + INSERT INTO streetname VALUES('bell glen'); + INSERT INTO streetname VALUES('bellmore'); + INSERT INTO streetname VALUES('bells mill'); + INSERT INTO streetname VALUES('bellville'); + INSERT INTO streetname VALUES('belmar place'); + INSERT INTO streetname VALUES('bembridge'); + INSERT INTO streetname VALUES('bennett neely'); + INSERT INTO streetname VALUES('bentgrass run'); + INSERT INTO streetname VALUES('benthaven'); + INSERT INTO streetname VALUES('bernardy'); + INSERT INTO streetname VALUES('bernbrook shadow'); + INSERT INTO streetname VALUES('berrybrook'); + INSERT INTO streetname VALUES('berrybush'); + INSERT INTO streetname VALUES('berwick'); + INSERT INTO streetname VALUES('betterton'); + INSERT INTO streetname VALUES('bickham'); + INSERT INTO streetname VALUES('billingham'); + INSERT INTO streetname VALUES('birchcroft'); + INSERT INTO streetname VALUES('birchstone'); + INSERT INTO streetname VALUES('birdwell'); + INSERT INTO streetname VALUES('bisaner'); + INSERT INTO streetname VALUES('bitterbush'); + INSERT INTO streetname VALUES('bitterroot'); + INSERT INTO streetname VALUES('black fox'); + INSERT INTO streetname VALUES('black maple'); + INSERT INTO streetname VALUES('black trail'); + INSERT INTO streetname VALUES('blackbird'); + INSERT INTO streetname VALUES('blake a dare'); + INSERT INTO streetname VALUES('blasdell'); + INSERT INTO streetname VALUES('blue aster'); + INSERT INTO streetname VALUES('blue finch'); + INSERT INTO streetname VALUES('blue lilac'); + INSERT INTO streetname VALUES('blue sky'); + INSERT INTO streetname VALUES('blue tick'); + INSERT INTO streetname VALUES('bob beatty'); + INSERT INTO streetname VALUES('bobcat'); + INSERT INTO streetname VALUES('bolton'); + INSERT INTO streetname VALUES('boomerang'); + INSERT INTO streetname VALUES('boulder'); + INSERT INTO streetname VALUES('boxer'); + INSERT INTO streetname VALUES('boxmeer'); + INSERT INTO streetname VALUES('brachnell view'); + INSERT INTO streetname VALUES('bradford lake'); + INSERT INTO streetname VALUES('bradwell'); + INSERT INTO streetname VALUES('brady'); + INSERT INTO streetname VALUES('braids bend'); + INSERT INTO streetname VALUES('bralers'); + INSERT INTO streetname VALUES('brandie glen'); + INSERT INTO streetname VALUES('brandy ridge'); + INSERT INTO streetname VALUES('brandybuck'); + INSERT INTO streetname VALUES('branthurst'); + INSERT INTO streetname VALUES('brassy creek'); + INSERT INTO streetname VALUES('brathay'); + INSERT INTO streetname VALUES('brawer farm'); + INSERT INTO streetname VALUES('breezy morn'); + INSERT INTO streetname VALUES('brenda'); + INSERT INTO streetname VALUES('brenly'); + INSERT INTO streetname VALUES('brenock'); + INSERT INTO streetname VALUES('brianwood'); + INSERT INTO streetname VALUES('briar rose'); + INSERT INTO streetname VALUES('briarcrest'); + INSERT INTO streetname VALUES('briarthorne'); + INSERT INTO streetname VALUES('brick dust'); + INSERT INTO streetname VALUES('bridgepath'); + INSERT INTO streetname VALUES('bridle ridge'); + INSERT INTO streetname VALUES('briggs'); + INSERT INTO streetname VALUES('brightleaf'); + INSERT INTO streetname VALUES('brigstock'); + INSERT INTO streetname VALUES('broad ridge'); + INSERT INTO streetname VALUES('brock'); + INSERT INTO streetname VALUES('brockhampton'); + INSERT INTO streetname VALUES('broken pine'); + INSERT INTO streetname VALUES('brompton'); + INSERT INTO streetname VALUES('brook falls'); + INSERT INTO streetname VALUES('brookings'); + INSERT INTO streetname VALUES('browne'); + INSERT INTO streetname VALUES('brownes creek'); + INSERT INTO streetname VALUES('brownes ferry'); + INSERT INTO streetname VALUES('brownestone view'); + INSERT INTO streetname VALUES('brumit'); + INSERT INTO streetname VALUES('bryn athyn'); + INSERT INTO streetname VALUES('buck'); + INSERT INTO streetname VALUES('bucklebury'); + INSERT INTO streetname VALUES('buckminister'); + INSERT INTO streetname VALUES('buckspring'); + INSERT INTO streetname VALUES('burch'); + INSERT INTO streetname VALUES('burch shire'); + INSERT INTO streetname VALUES('burkston'); + INSERT INTO streetname VALUES('burmith'); + INSERT INTO streetname VALUES('burnaby'); + INSERT INTO streetname VALUES('butterfly'); + INSERT INTO streetname VALUES('cabin creek'); + INSERT INTO streetname VALUES('cairns mill'); + INSERT INTO streetname VALUES('callender'); + INSERT INTO streetname VALUES('cambellton'); + INSERT INTO streetname VALUES('cambridge bay'); + INSERT INTO streetname VALUES('canary'); + INSERT INTO streetname VALUES('canbury'); + INSERT INTO streetname VALUES('candle leaf'); + INSERT INTO streetname VALUES('canipe'); + INSERT INTO streetname VALUES('canipe farm'); + INSERT INTO streetname VALUES('cannon'); + INSERT INTO streetname VALUES('canopy'); + INSERT INTO streetname VALUES('canso'); + INSERT INTO streetname VALUES('canterbrook'); + INSERT INTO streetname VALUES('cardinal glen'); + INSERT INTO streetname VALUES('cardinal point'); + INSERT INTO streetname VALUES('cardinals nest'); + INSERT INTO streetname VALUES('carlota'); + INSERT INTO streetname VALUES('carmathen'); + INSERT INTO streetname VALUES('carver'); + INSERT INTO streetname VALUES('carver pond'); + INSERT INTO streetname VALUES('casa loma'); + INSERT INTO streetname VALUES('caselton'); + INSERT INTO streetname VALUES('castello'); + INSERT INTO streetname VALUES('castle ridge'); + INSERT INTO streetname VALUES('castleglen'); + INSERT INTO streetname VALUES('castlemaine'); + INSERT INTO streetname VALUES('cavett'); + INSERT INTO streetname VALUES('caymus'); + INSERT INTO streetname VALUES('cedardale ridge'); + INSERT INTO streetname VALUES('cedarhurst'); + INSERT INTO streetname VALUES('cemkey way'); + INSERT INTO streetname VALUES('cerise'); + INSERT INTO streetname VALUES('chaceview'); + INSERT INTO streetname VALUES('chadsworth'); + INSERT INTO streetname VALUES('chadwell'); + INSERT INTO streetname VALUES('champions crest'); + INSERT INTO streetname VALUES('chandler haven'); + INSERT INTO streetname VALUES('chapel crossing'); + INSERT INTO streetname VALUES('chapel ridge'); + INSERT INTO streetname VALUES('charles crawford'); + INSERT INTO streetname VALUES('charminster'); + INSERT INTO streetname VALUES('chasewind'); + INSERT INTO streetname VALUES('chavel'); + INSERT INTO streetname VALUES('chelsea jade'); + INSERT INTO streetname VALUES('chestnut knoll'); + INSERT INTO streetname VALUES('cheviot'); + INSERT INTO streetname VALUES('chickadee'); + INSERT INTO streetname VALUES('chidley'); + INSERT INTO streetname VALUES('chimney ridge'); + INSERT INTO streetname VALUES('chimney springs'); + INSERT INTO streetname VALUES('chinaberry'); + INSERT INTO streetname VALUES('chinemist'); + INSERT INTO streetname VALUES('chinquapin'); + INSERT INTO streetname VALUES('chiswell'); + INSERT INTO streetname VALUES('christenbury'); + INSERT INTO streetname VALUES('christenbury hills'); + INSERT INTO streetname VALUES('churchill'); + INSERT INTO streetname VALUES('cindy'); + INSERT INTO streetname VALUES('cinnamon teal'); + INSERT INTO streetname VALUES('citadel'); + INSERT INTO streetname VALUES('clare olivia'); + INSERT INTO streetname VALUES('clarke creek'); + INSERT INTO streetname VALUES('clarke ridge'); + INSERT INTO streetname VALUES('clear day'); + INSERT INTO streetname VALUES('clear stream'); + INSERT INTO streetname VALUES('cleve brown'); + INSERT INTO streetname VALUES('cliff cameron'); + INSERT INTO streetname VALUES('cliffvale'); + INSERT INTO streetname VALUES('cloverside'); + INSERT INTO streetname VALUES('clymer'); + INSERT INTO streetname VALUES('coatbridge'); + INSERT INTO streetname VALUES('cobble glen'); + INSERT INTO streetname VALUES('cochran farm'); + INSERT INTO streetname VALUES('cochrane'); + INSERT INTO streetname VALUES('coleridge'); + INSERT INTO streetname VALUES('coleshire'); + INSERT INTO streetname VALUES('collins'); + INSERT INTO streetname VALUES('colvard'); + INSERT INTO streetname VALUES('colvard park'); + INSERT INTO streetname VALUES('condor'); + INSERT INTO streetname VALUES('conner ridge'); + INSERT INTO streetname VALUES('connery'); + INSERT INTO streetname VALUES('cooper run'); + INSERT INTO streetname VALUES('coopers ridge'); + INSERT INTO streetname VALUES('copper hill'); + INSERT INTO streetname VALUES('coppermine'); + INSERT INTO streetname VALUES('cornelia'); + INSERT INTO streetname VALUES('corner'); + INSERT INTO streetname VALUES('cornerstone'); + INSERT INTO streetname VALUES('cottage oaks'); + INSERT INTO streetname VALUES('cougar'); + INSERT INTO streetname VALUES('coves end'); + INSERT INTO streetname VALUES('cragland'); + INSERT INTO streetname VALUES('crail'); + INSERT INTO streetname VALUES('cranberry nook'); + INSERT INTO streetname VALUES('crawford brook'); + INSERT INTO streetname VALUES('crayton'); + INSERT INTO streetname VALUES('creek breeze'); + INSERT INTO streetname VALUES('crescent ridge'); + INSERT INTO streetname VALUES('crescent view'); + INSERT INTO streetname VALUES('cresta'); + INSERT INTO streetname VALUES('crestfield'); + INSERT INTO streetname VALUES('crestland'); + INSERT INTO streetname VALUES('crestwick'); + INSERT INTO streetname VALUES('crisfield'); + INSERT INTO streetname VALUES('crisp wood'); + INSERT INTO streetname VALUES('croft haven'); + INSERT INTO streetname VALUES('crofton springs'); + INSERT INTO streetname VALUES('cross'); + INSERT INTO streetname VALUES('crosspoint center'); + INSERT INTO streetname VALUES('crownvista'); + INSERT INTO streetname VALUES('crystal arms'); + INSERT INTO streetname VALUES('crystal crest'); + INSERT INTO streetname VALUES('crystal leaf'); + INSERT INTO streetname VALUES('cunningham park'); + INSERT INTO streetname VALUES('cypress pond'); + INSERT INTO streetname VALUES('daffodil'); + INSERT INTO streetname VALUES('daisyfield'); + INSERT INTO streetname VALUES('dalecrest'); + INSERT INTO streetname VALUES('dannelly park'); + INSERT INTO streetname VALUES('daphne'); + INSERT INTO streetname VALUES('daria'); + INSERT INTO streetname VALUES('dartmouth'); + INSERT INTO streetname VALUES('datha'); + INSERT INTO streetname VALUES('david cox'); + INSERT INTO streetname VALUES('davis'); + INSERT INTO streetname VALUES('davis crossing'); + INSERT INTO streetname VALUES('davis lake'); + INSERT INTO streetname VALUES('davis ridge'); + INSERT INTO streetname VALUES('dawnmist'); + INSERT INTO streetname VALUES('daybreak'); + INSERT INTO streetname VALUES('dearmon'); + INSERT INTO streetname VALUES('dearview'); + INSERT INTO streetname VALUES('deaton hill'); + INSERT INTO streetname VALUES('deer cross'); + INSERT INTO streetname VALUES('deerton'); + INSERT INTO streetname VALUES('degrasse'); + INSERT INTO streetname VALUES('delamere'); + INSERT INTO streetname VALUES('dellfield'); + INSERT INTO streetname VALUES('dellinger'); + INSERT INTO streetname VALUES('demington'); + INSERT INTO streetname VALUES('denmeade'); + INSERT INTO streetname VALUES('derita'); + INSERT INTO streetname VALUES('derita woods'); + INSERT INTO streetname VALUES('deruyter'); + INSERT INTO streetname VALUES('dervish'); + INSERT INTO streetname VALUES('devas'); + INSERT INTO streetname VALUES('devon croft'); + INSERT INTO streetname VALUES('devonbridge'); + INSERT INTO streetname VALUES('devongate'); + INSERT INTO streetname VALUES('devonhill'); + INSERT INTO streetname VALUES('dewmorn'); + INSERT INTO streetname VALUES('distribution center'); + INSERT INTO streetname VALUES('dominion crest'); + INSERT INTO streetname VALUES('dominion green'); + INSERT INTO streetname VALUES('dominion village'); + INSERT INTO streetname VALUES('dorshire'); + INSERT INTO streetname VALUES('double creek crossing'); + INSERT INTO streetname VALUES('dow'); + INSERT INTO streetname VALUES('downfield wood'); + INSERT INTO streetname VALUES('downing creek'); + INSERT INTO streetname VALUES('driscol'); + INSERT INTO streetname VALUES('driwood'); + INSERT INTO streetname VALUES('dry brook'); + INSERT INTO streetname VALUES('dumont'); + INSERT INTO streetname VALUES('dunblane'); + INSERT INTO streetname VALUES('dunfield'); + INSERT INTO streetname VALUES('dunoon'); + INSERT INTO streetname VALUES('dunslow'); + INSERT INTO streetname VALUES('dunstaff'); + INSERT INTO streetname VALUES('durham'); + INSERT INTO streetname VALUES('durston'); + INSERT INTO streetname VALUES('dusty cedar'); + INSERT INTO streetname VALUES('dusty trail'); + INSERT INTO streetname VALUES('dutchess'); + INSERT INTO streetname VALUES('duxford'); + INSERT INTO streetname VALUES('eagle creek'); + INSERT INTO streetname VALUES('eagles field'); + INSERT INTO streetname VALUES('eargle'); + INSERT INTO streetname VALUES('earlswood'); + INSERT INTO streetname VALUES('early mist'); + INSERT INTO streetname VALUES('earthenware'); + INSERT INTO streetname VALUES('eastfield park'); + INSERT INTO streetname VALUES('eastfield village'); + INSERT INTO streetname VALUES('easy'); + INSERT INTO streetname VALUES('eben'); + INSERT INTO streetname VALUES('edgepine'); + INSERT INTO streetname VALUES('edgewier'); + INSERT INTO streetname VALUES('edinburgh'); + INSERT INTO streetname VALUES('edinmeadow'); + INSERT INTO streetname VALUES('edmonton'); + INSERT INTO streetname VALUES('edwin jones'); + INSERT INTO streetname VALUES('elberon'); + INSERT INTO streetname VALUES('elderslie'); + INSERT INTO streetname VALUES('elementary view'); + INSERT INTO streetname VALUES('elendil'); + INSERT INTO streetname VALUES('elizabeth'); + INSERT INTO streetname VALUES('elm cove'); + INSERT INTO streetname VALUES('elrond'); + INSERT INTO streetname VALUES('elsenham'); + INSERT INTO streetname VALUES('elven'); + INSERT INTO streetname VALUES('emma lynn'); + INSERT INTO streetname VALUES('english setter'); + INSERT INTO streetname VALUES('enoch'); + INSERT INTO streetname VALUES('equipment'); + INSERT INTO streetname VALUES('ernest russell'); + INSERT INTO streetname VALUES('ernie'); + INSERT INTO streetname VALUES('esmeralda'); + INSERT INTO streetname VALUES('evergreen hollow'); + INSERT INTO streetname VALUES('eversfield'); + INSERT INTO streetname VALUES('ewen'); + INSERT INTO streetname VALUES('ewert cut'); + INSERT INTO streetname VALUES('exbury'); + INSERT INTO streetname VALUES('fair grounds park'); + INSERT INTO streetname VALUES('fairbourne'); + INSERT INTO streetname VALUES('fairchase'); + INSERT INTO streetname VALUES('faircreek'); + INSERT INTO streetname VALUES('fairglen'); + INSERT INTO streetname VALUES('fairlea'); + INSERT INTO streetname VALUES('fairmead'); + INSERT INTO streetname VALUES('fairmeadows'); + INSERT INTO streetname VALUES('fairstone'); + INSERT INTO streetname VALUES('fairvista'); + INSERT INTO streetname VALUES('fairway point'); + INSERT INTO streetname VALUES('falconcrest'); + INSERT INTO streetname VALUES('falls ridge'); + INSERT INTO streetname VALUES('falmouth'); + INSERT INTO streetname VALUES('far west'); + INSERT INTO streetname VALUES('farlow'); + INSERT INTO streetname VALUES('farris wheel'); + INSERT INTO streetname VALUES('fawndale'); + INSERT INTO streetname VALUES('feather bend'); + INSERT INTO streetname VALUES('fernledge'); + INSERT INTO streetname VALUES('fernmoss'); + INSERT INTO streetname VALUES('ferrell commons'); + INSERT INTO streetname VALUES('fieldstone'); + INSERT INTO streetname VALUES('fillian'); + INSERT INTO streetname VALUES('fincher'); + INSERT INTO streetname VALUES('foggy meadow'); + INSERT INTO streetname VALUES('fordyce'); + INSERT INTO streetname VALUES('forest grove'); + INSERT INTO streetname VALUES('forest path'); + INSERT INTO streetname VALUES('forestridge commons'); + INSERT INTO streetname VALUES('forestrock'); + INSERT INTO streetname VALUES('fortunes ridge'); + INSERT INTO streetname VALUES('founders club'); + INSERT INTO streetname VALUES('fountaingrass'); + INSERT INTO streetname VALUES('fox chase'); + INSERT INTO streetname VALUES('fox glen'); + INSERT INTO streetname VALUES('fox hill'); + INSERT INTO streetname VALUES('fox point'); + INSERT INTO streetname VALUES('fox trot'); + INSERT INTO streetname VALUES('foxbriar'); + INSERT INTO streetname VALUES('frank little'); + INSERT INTO streetname VALUES('franzia'); + INSERT INTO streetname VALUES('french woods'); + INSERT INTO streetname VALUES('frostmoor'); + INSERT INTO streetname VALUES('frye'); + INSERT INTO streetname VALUES('furlong'); + INSERT INTO streetname VALUES('galena view'); + INSERT INTO streetname VALUES('gallery pointe'); + INSERT INTO streetname VALUES('gammon'); + INSERT INTO streetname VALUES('garden grove'); + INSERT INTO streetname VALUES('gardendale'); + INSERT INTO streetname VALUES('garganey'); + INSERT INTO streetname VALUES('garnet field'); + INSERT INTO streetname VALUES('garrison'); + INSERT INTO streetname VALUES('garvin'); + INSERT INTO streetname VALUES('garvis'); + INSERT INTO streetname VALUES('gaskill'); + INSERT INTO streetname VALUES('gemstone'); + INSERT INTO streetname VALUES('gibbon'); + INSERT INTO streetname VALUES('gibbon terrace'); + INSERT INTO streetname VALUES('gibbons link'); + INSERT INTO streetname VALUES('gillman'); + INSERT INTO streetname VALUES('gladwood'); + INSERT INTO streetname VALUES('gladwyne'); + INSERT INTO streetname VALUES('glamorgan'); + INSERT INTO streetname VALUES('glaze'); + INSERT INTO streetname VALUES('glen brook'); + INSERT INTO streetname VALUES('glen cove'); + INSERT INTO streetname VALUES('glen hope'); + INSERT INTO streetname VALUES('glen manor'); + INSERT INTO streetname VALUES('glen olden'); + INSERT INTO streetname VALUES('glencairn'); + INSERT INTO streetname VALUES('glendock'); + INSERT INTO streetname VALUES('glenolden'); + INSERT INTO streetname VALUES('glenover'); + INSERT INTO streetname VALUES('glenshire'); + INSERT INTO streetname VALUES('glenstone'); + INSERT INTO streetname VALUES('gold dust'); + INSERT INTO streetname VALUES('golden pond'); + INSERT INTO streetname VALUES('goldenblush'); + INSERT INTO streetname VALUES('goldenfield'); + INSERT INTO streetname VALUES('goose landing'); + INSERT INTO streetname VALUES('gorham gate'); + INSERT INTO streetname VALUES('grabill'); + INSERT INTO streetname VALUES('graburns ford'); + INSERT INTO streetname VALUES('graham'); + INSERT INTO streetname VALUES('grahamson'); + INSERT INTO streetname VALUES('granard'); + INSERT INTO streetname VALUES('grand teton'); + INSERT INTO streetname VALUES('grande heights'); + INSERT INTO streetname VALUES('grandeur'); + INSERT INTO streetname VALUES('granite creek'); + INSERT INTO streetname VALUES('grasset'); + INSERT INTO streetname VALUES('graypark'); + INSERT INTO streetname VALUES('grays ridge'); + INSERT INTO streetname VALUES('great bear'); + INSERT INTO streetname VALUES('green clover'); + INSERT INTO streetname VALUES('green hedge'); + INSERT INTO streetname VALUES('green meadow'); + INSERT INTO streetname VALUES('green pasture'); + INSERT INTO streetname VALUES('greene'); + INSERT INTO streetname VALUES('greenloch'); + INSERT INTO streetname VALUES('greenock ridge'); + INSERT INTO streetname VALUES('greenware'); + INSERT INTO streetname VALUES('greenway village'); + INSERT INTO streetname VALUES('grenelefe village'); + INSERT INTO streetname VALUES('grey dogwood'); + INSERT INTO streetname VALUES('greyhound'); + INSERT INTO streetname VALUES('greylock ridge'); + INSERT INTO streetname VALUES('grosbeak'); + INSERT INTO streetname VALUES('grove'); + INSERT INTO streetname VALUES('groveton'); + INSERT INTO streetname VALUES('groveview'); + INSERT INTO streetname VALUES('hackberry creek'); + INSERT INTO streetname VALUES('hackberry grove'); + INSERT INTO streetname VALUES('hackett'); + INSERT INTO streetname VALUES('haddington'); + INSERT INTO streetname VALUES('hagler'); + INSERT INTO streetname VALUES('halcott'); + INSERT INTO streetname VALUES('half dome'); + INSERT INTO streetname VALUES('hallam'); + INSERT INTO streetname VALUES('hamilton russell'); + INSERT INTO streetname VALUES('hampton place'); + INSERT INTO streetname VALUES('hankins'); + INSERT INTO streetname VALUES('harburn forest'); + INSERT INTO streetname VALUES('harringham'); + INSERT INTO streetname VALUES('harrington woods'); + INSERT INTO streetname VALUES('harris corners'); + INSERT INTO streetname VALUES('harris cove'); + INSERT INTO streetname VALUES('harris glen'); + INSERT INTO streetname VALUES('harris hill'); + INSERT INTO streetname VALUES('harris oak'); + INSERT INTO streetname VALUES('harris pointe'); + INSERT INTO streetname VALUES('harris pond'); + INSERT INTO streetname VALUES('harris ridge'); + INSERT INTO streetname VALUES('harris technology'); + INSERT INTO streetname VALUES('harris woods'); + INSERT INTO streetname VALUES('hartfield downs'); + INSERT INTO streetname VALUES('hattie little'); + INSERT INTO streetname VALUES('hatwynn'); + INSERT INTO streetname VALUES('hawkins'); + INSERT INTO streetname VALUES('hawksnest'); + INSERT INTO streetname VALUES('haybridge'); + INSERT INTO streetname VALUES('hayden'); + INSERT INTO streetname VALUES('hazelcroft'); + INSERT INTO streetname VALUES('hazlitt'); + INSERT INTO streetname VALUES('hazy valley'); + INSERT INTO streetname VALUES('hearst'); + INSERT INTO streetname VALUES('heathcrest'); + INSERT INTO streetname VALUES('heathcroft'); + INSERT INTO streetname VALUES('hedge maple'); + INSERT INTO streetname VALUES('hedgecrest'); + INSERT INTO streetname VALUES('hedingham'); + INSERT INTO streetname VALUES('heman'); + INSERT INTO streetname VALUES('henderson'); + INSERT INTO streetname VALUES('henderson oaks'); + INSERT INTO streetname VALUES('henderson valley'); + INSERT INTO streetname VALUES('hendry'); + INSERT INTO streetname VALUES('heritage hills'); + INSERT INTO streetname VALUES('heritage woods'); + INSERT INTO streetname VALUES('heron cove'); + INSERT INTO streetname VALUES('heron glen'); + INSERT INTO streetname VALUES('hewitt'); + INSERT INTO streetname VALUES('hey rock'); + INSERT INTO streetname VALUES('heysham'); + INSERT INTO streetname VALUES('hickory cove'); + INSERT INTO streetname VALUES('hidden meadow'); + INSERT INTO streetname VALUES('high glen'); + INSERT INTO streetname VALUES('high laurel'); + INSERT INTO streetname VALUES('high valley'); + INSERT INTO streetname VALUES('highcroft'); + INSERT INTO streetname VALUES('highland'); + INSERT INTO streetname VALUES('highland commons'); + INSERT INTO streetname VALUES('highland creek'); + INSERT INTO streetname VALUES('highland glen'); + INSERT INTO streetname VALUES('highland park'); + INSERT INTO streetname VALUES('highlander'); + INSERT INTO streetname VALUES('highstream'); + INSERT INTO streetname VALUES('hilltop'); + INSERT INTO streetname VALUES('hobbitshire'); + INSERT INTO streetname VALUES('hoffman'); + INSERT INTO streetname VALUES('hogans way'); + INSERT INTO streetname VALUES('holbert'); + INSERT INTO streetname VALUES('hollow ridge'); + INSERT INTO streetname VALUES('holly vista'); + INSERT INTO streetname VALUES('hollywood'); + INSERT INTO streetname VALUES('hoover'); + INSERT INTO streetname VALUES('hopkins'); + INSERT INTO streetname VALUES('horace mann'); + INSERT INTO streetname VALUES('hornbeam'); + INSERT INTO streetname VALUES('horse pasture'); + INSERT INTO streetname VALUES('hosta'); + INSERT INTO streetname VALUES('howard'); + INSERT INTO streetname VALUES('hubbard'); + INSERT INTO streetname VALUES('hubbard falls'); + INSERT INTO streetname VALUES('hubbard woods'); + INSERT INTO streetname VALUES('hucks'); + INSERT INTO streetname VALUES('hunters creek'); + INSERT INTO streetname VALUES('hunters pointe'); + INSERT INTO streetname VALUES('hunters spring'); + INSERT INTO streetname VALUES('hunters whip'); + INSERT INTO streetname VALUES('huntmeadow'); + INSERT INTO streetname VALUES('hutchison mcdonald'); + INSERT INTO streetname VALUES('ingleton'); + INSERT INTO streetname VALUES('insdale'); + INSERT INTO streetname VALUES('interstate 85 service'); + INSERT INTO streetname VALUES('iola'); + INSERT INTO streetname VALUES('iredell'); + INSERT INTO streetname VALUES('iron brigade'); + INSERT INTO streetname VALUES('irwin valley'); + INSERT INTO streetname VALUES('irwin wood'); + INSERT INTO streetname VALUES('ivy brook'); + INSERT INTO streetname VALUES('ivy ridge'); + INSERT INTO streetname VALUES('jack russell'); + INSERT INTO streetname VALUES('jackson'); + INSERT INTO streetname VALUES('jacob martin'); + INSERT INTO streetname VALUES('jamison'); + INSERT INTO streetname VALUES('jane'); + INSERT INTO streetname VALUES('jaspar crest'); + INSERT INTO streetname VALUES('jessica'); + INSERT INTO streetname VALUES('jimmy oehler'); + INSERT INTO streetname VALUES('jocelyn'); + INSERT INTO streetname VALUES('johnston mill'); + INSERT INTO streetname VALUES('johnston oehler'); + INSERT INTO streetname VALUES('judal'); + INSERT INTO streetname VALUES('junipeous'); + INSERT INTO streetname VALUES('juniper'); + INSERT INTO streetname VALUES('juniperus'); + INSERT INTO streetname VALUES('kalispell'); + INSERT INTO streetname VALUES('karylsturn'); + INSERT INTO streetname VALUES('katelyn'); + INSERT INTO streetname VALUES('kayron'); + INSERT INTO streetname VALUES('keaton'); + INSERT INTO streetname VALUES('keble'); + INSERT INTO streetname VALUES('keels'); + INSERT INTO streetname VALUES('keith'); + INSERT INTO streetname VALUES('keithwood'); + INSERT INTO streetname VALUES('kelden walker'); + INSERT INTO streetname VALUES('kelsey emma'); + INSERT INTO streetname VALUES('kendrick'); + INSERT INTO streetname VALUES('kenmont'); + INSERT INTO streetname VALUES('kennerly cove'); + INSERT INTO streetname VALUES('kenninghall'); + INSERT INTO streetname VALUES('kent village'); + INSERT INTO streetname VALUES('kestral ridge'); + INSERT INTO streetname VALUES('kestrel'); + INSERT INTO streetname VALUES('kilmartin'); + INSERT INTO streetname VALUES('kilty'); + INSERT INTO streetname VALUES('kinglet'); + INSERT INTO streetname VALUES('kingsland'); + INSERT INTO streetname VALUES('kingsnorth'); + INSERT INTO streetname VALUES('kinsmore'); + INSERT INTO streetname VALUES('kirkgard'); + INSERT INTO streetname VALUES('kirkmont'); + INSERT INTO streetname VALUES('knightsgate'); + INSERT INTO streetname VALUES('kobuk'); + INSERT INTO streetname VALUES('kotlik'); + INSERT INTO streetname VALUES('kotz'); + INSERT INTO streetname VALUES('kyndall walk'); + INSERT INTO streetname VALUES('laborde'); + INSERT INTO streetname VALUES('lady bank'); + INSERT INTO streetname VALUES('lagrande'); + INSERT INTO streetname VALUES('lake'); + INSERT INTO streetname VALUES('lakeridge commons'); + INSERT INTO streetname VALUES('lakeview'); + INSERT INTO streetname VALUES('lakewood edge'); + INSERT INTO streetname VALUES('lakota'); + INSERT INTO streetname VALUES('lambrook'); + INSERT INTO streetname VALUES('lampkin'); + INSERT INTO streetname VALUES('lampkin park'); + INSERT INTO streetname VALUES('langham'); + INSERT INTO streetname VALUES('lanzerac manor'); + INSERT INTO streetname VALUES('larkmead forest'); + INSERT INTO streetname VALUES('lattice'); + INSERT INTO streetname VALUES('laurel crest'); + INSERT INTO streetname VALUES('laurel ridge'); + INSERT INTO streetname VALUES('laurel run'); + INSERT INTO streetname VALUES('laurenfield'); + INSERT INTO streetname VALUES('laveta'); + INSERT INTO streetname VALUES('lazy day'); + INSERT INTO streetname VALUES('leawood run'); + INSERT INTO streetname VALUES('lee marie'); + INSERT INTO streetname VALUES('legacy lake'); + INSERT INTO streetname VALUES('legacy park'); + INSERT INTO streetname VALUES('legato'); + INSERT INTO streetname VALUES('legolas'); + INSERT INTO streetname VALUES('leigh glen'); + INSERT INTO streetname VALUES('lence'); + INSERT INTO streetname VALUES('lenox hill'); + INSERT INTO streetname VALUES('leonine'); + INSERT INTO streetname VALUES('leslie'); + INSERT INTO streetname VALUES('lester hill'); + INSERT INTO streetname VALUES('levisey'); + INSERT INTO streetname VALUES('liberty bell'); + INSERT INTO streetname VALUES('linden berry'); + INSERT INTO streetname VALUES('lisbon'); + INSERT INTO streetname VALUES('little stoney'); + INSERT INTO streetname VALUES('livengood'); + INSERT INTO streetname VALUES('lochway'); + INSERT INTO streetname VALUES('lockman'); + INSERT INTO streetname VALUES('loganville'); + INSERT INTO streetname VALUES('lone tree'); + INSERT INTO streetname VALUES('long creek park'); + INSERT INTO streetname VALUES('long forest'); + INSERT INTO streetname VALUES('looking glass'); + INSERT INTO streetname VALUES('lookout point'); + INSERT INTO streetname VALUES('lowen'); + INSERT INTO streetname VALUES('lusby'); + INSERT INTO streetname VALUES('lyleton'); + INSERT INTO streetname VALUES('lynn lee'); + INSERT INTO streetname VALUES('lynnewood glen'); + INSERT INTO streetname VALUES('machrie'); + INSERT INTO streetname VALUES('mackinac'); + INSERT INTO streetname VALUES('maddox'); + INSERT INTO streetname VALUES('madison park'); + INSERT INTO streetname VALUES('mallard'); + INSERT INTO streetname VALUES('mallard cove'); + INSERT INTO streetname VALUES('mallard forest'); + INSERT INTO streetname VALUES('mallard grove'); + INSERT INTO streetname VALUES('mallard hill'); + INSERT INTO streetname VALUES('mallard park'); + INSERT INTO streetname VALUES('mallard ridge'); + INSERT INTO streetname VALUES('mallard view'); + INSERT INTO streetname VALUES('manbey'); + INSERT INTO streetname VALUES('manning'); + INSERT INTO streetname VALUES('mantario'); + INSERT INTO streetname VALUES('maple'); + INSERT INTO streetname VALUES('maple cove'); + INSERT INTO streetname VALUES('maple park'); + INSERT INTO streetname VALUES('marathon hill'); + INSERT INTO streetname VALUES('marbury'); + INSERT INTO streetname VALUES('marett'); + INSERT INTO streetname VALUES('marigold'); + INSERT INTO streetname VALUES('marionwood'); + INSERT INTO streetname VALUES('marshbank'); + INSERT INTO streetname VALUES('mason'); + INSERT INTO streetname VALUES('mayapple'); + INSERT INTO streetname VALUES('maylandia'); + INSERT INTO streetname VALUES('mayspring'); + INSERT INTO streetname VALUES('mcadam'); + INSERT INTO streetname VALUES('mcchesney'); + INSERT INTO streetname VALUES('mccurdy'); + INSERT INTO streetname VALUES('mcgrath'); + INSERT INTO streetname VALUES('mckendree'); + INSERT INTO streetname VALUES('mclaughlin'); + INSERT INTO streetname VALUES('mctaggart'); + INSERT INTO streetname VALUES('meadow green'); + INSERT INTO streetname VALUES('meadow knoll'); + INSERT INTO streetname VALUES('meadow post'); + INSERT INTO streetname VALUES('meadowmont'); + INSERT INTO streetname VALUES('meadowmont view'); + INSERT INTO streetname VALUES('meadowview hills'); + INSERT INTO streetname VALUES('melshire'); + INSERT INTO streetname VALUES('melstrand'); + INSERT INTO streetname VALUES('mentone'); + INSERT INTO streetname VALUES('meridale crossing'); + INSERT INTO streetname VALUES('merion hills'); + INSERT INTO streetname VALUES('merlot'); + INSERT INTO streetname VALUES('mersham'); + INSERT INTO streetname VALUES('metromont'); + INSERT INTO streetname VALUES('metromont industrial'); + INSERT INTO streetname VALUES('michaw'); + INSERT INTO streetname VALUES('milhaven'); + INSERT INTO streetname VALUES('milhof'); + INSERT INTO streetname VALUES('millstream ridge'); + INSERT INTO streetname VALUES('mineral ridge'); + INSERT INTO streetname VALUES('mint thistle'); + INSERT INTO streetname VALUES('mintleaf'); + INSERT INTO streetname VALUES('mintvale'); + INSERT INTO streetname VALUES('misty'); + INSERT INTO streetname VALUES('misty arbor'); + INSERT INTO streetname VALUES('misty creek'); + INSERT INTO streetname VALUES('misty oaks'); + INSERT INTO streetname VALUES('misty wood'); + INSERT INTO streetname VALUES('mitzi deborah'); + INSERT INTO streetname VALUES('mobile'); + INSERT INTO streetname VALUES('molly elizabeth'); + INSERT INTO streetname VALUES('monmouth'); + INSERT INTO streetname VALUES('montrose'); + INSERT INTO streetname VALUES('moonlight'); + INSERT INTO streetname VALUES('moose'); + INSERT INTO streetname VALUES('morning dew'); + INSERT INTO streetname VALUES('morningsong'); + INSERT INTO streetname VALUES('morningview'); + INSERT INTO streetname VALUES('morsey'); + INSERT INTO streetname VALUES('moss glen'); + INSERT INTO streetname VALUES('mossy bank'); + INSERT INTO streetname VALUES('motor sport'); + INSERT INTO streetname VALUES('mountain laurel'); + INSERT INTO streetname VALUES('mourning dove'); + INSERT INTO streetname VALUES('mozart'); + INSERT INTO streetname VALUES('munsing'); + INSERT INTO streetname VALUES('murray'); + INSERT INTO streetname VALUES('nathan'); + INSERT INTO streetname VALUES('netherhall'); + INSERT INTO streetname VALUES('netherton'); + INSERT INTO streetname VALUES('neuhoff'); + INSERT INTO streetname VALUES('nevin'); + INSERT INTO streetname VALUES('nevin brook'); + INSERT INTO streetname VALUES('nevin glen'); + INSERT INTO streetname VALUES('nevin place'); + INSERT INTO streetname VALUES('new england'); + INSERT INTO streetname VALUES('new house'); + INSERT INTO streetname VALUES('newbary'); + INSERT INTO streetname VALUES('newchurch'); + INSERT INTO streetname VALUES('newfane'); + INSERT INTO streetname VALUES('newgard'); + INSERT INTO streetname VALUES('nicholas'); + INSERT INTO streetname VALUES('nicole'); + INSERT INTO streetname VALUES('nobility'); + INSERT INTO streetname VALUES('norcroft'); + INSERT INTO streetname VALUES('northridge'); + INSERT INTO streetname VALUES('northside'); + INSERT INTO streetname VALUES('northwoods business'); + INSERT INTO streetname VALUES('norway'); + INSERT INTO streetname VALUES('nottinghill'); + INSERT INTO streetname VALUES('numenore'); + INSERT INTO streetname VALUES('nyewood'); + INSERT INTO streetname VALUES('oak'); + INSERT INTO streetname VALUES('oak cove'); + INSERT INTO streetname VALUES('oak pasture'); + INSERT INTO streetname VALUES('oakburn'); + INSERT INTO streetname VALUES('oakwinds'); + INSERT INTO streetname VALUES('oakwood'); + INSERT INTO streetname VALUES('obrien'); + INSERT INTO streetname VALUES('ocala'); + INSERT INTO streetname VALUES('old bridge'); + INSERT INTO streetname VALUES('old fox'); + INSERT INTO streetname VALUES('old potters'); + INSERT INTO streetname VALUES('old statesville'); + INSERT INTO streetname VALUES('old steine'); + INSERT INTO streetname VALUES('old stoney creek'); + INSERT INTO streetname VALUES('old sugar creek'); + INSERT INTO streetname VALUES('old timber'); + INSERT INTO streetname VALUES('old wagon'); + INSERT INTO streetname VALUES('old willow'); + INSERT INTO streetname VALUES('oldenway'); + INSERT INTO streetname VALUES('oneida'); + INSERT INTO streetname VALUES('ontario'); + INSERT INTO streetname VALUES('oriole'); + INSERT INTO streetname VALUES('orofino'); + INSERT INTO streetname VALUES('orr'); + INSERT INTO streetname VALUES('osage'); + INSERT INTO streetname VALUES('osceola'); + INSERT INTO streetname VALUES('osprey knoll'); + INSERT INTO streetname VALUES('oxford hill'); + INSERT INTO streetname VALUES('painted fern'); + INSERT INTO streetname VALUES('painted pony'); + INSERT INTO streetname VALUES('paisley'); + INSERT INTO streetname VALUES('pale moss'); + INSERT INTO streetname VALUES('palladium'); + INSERT INTO streetname VALUES('palmutum'); + INSERT INTO streetname VALUES('palustris'); + INSERT INTO streetname VALUES('panglemont'); + INSERT INTO streetname VALUES('panther'); + INSERT INTO streetname VALUES('panthersville'); + INSERT INTO streetname VALUES('paper whites'); + INSERT INTO streetname VALUES('park'); + INSERT INTO streetname VALUES('parker green'); + INSERT INTO streetname VALUES('parkhouse'); + INSERT INTO streetname VALUES('passour ridge'); + INSERT INTO streetname VALUES('pasture view'); + INSERT INTO streetname VALUES('patricia ann'); + INSERT INTO streetname VALUES('patton'); + INSERT INTO streetname VALUES('patton ridge'); + INSERT INTO streetname VALUES('pawpaw'); + INSERT INTO streetname VALUES('peach'); + INSERT INTO streetname VALUES('peakwood'); + INSERT INTO streetname VALUES('pebble creek'); + INSERT INTO streetname VALUES('pecan cove'); + INSERT INTO streetname VALUES('pedigree'); + INSERT INTO streetname VALUES('pelorus'); + INSERT INTO streetname VALUES('penmore'); + INSERT INTO streetname VALUES('pensfold'); + INSERT INTO streetname VALUES('pepperstone'); + INSERT INTO streetname VALUES('peregrine'); + INSERT INTO streetname VALUES('periwinkle'); + INSERT INTO streetname VALUES('perkins'); + INSERT INTO streetname VALUES('pete brown'); + INSERT INTO streetname VALUES('phillips'); + INSERT INTO streetname VALUES('pickway'); + INSERT INTO streetname VALUES('piercy woods'); + INSERT INTO streetname VALUES('pierpoint'); + INSERT INTO streetname VALUES('pine'); + INSERT INTO streetname VALUES('pine branch'); + INSERT INTO streetname VALUES('pine meadow'); + INSERT INTO streetname VALUES('pineleaf'); + INSERT INTO streetname VALUES('pinewood'); + INSERT INTO streetname VALUES('pintail'); + INSERT INTO streetname VALUES('pipestone'); + INSERT INTO streetname VALUES('placer maple'); + INSERT INTO streetname VALUES('plover'); + INSERT INTO streetname VALUES('plum'); + INSERT INTO streetname VALUES('po box'); + INSERT INTO streetname VALUES('pochard'); + INSERT INTO streetname VALUES('pointview'); + INSERT INTO streetname VALUES('polk and white'); + INSERT INTO streetname VALUES('pond valley'); + INSERT INTO streetname VALUES('pondridge'); + INSERT INTO streetname VALUES('pope farm'); + INSERT INTO streetname VALUES('poplar grove'); + INSERT INTO streetname VALUES('poplar springs'); + INSERT INTO streetname VALUES('portola'); + INSERT INTO streetname VALUES('potters glen'); + INSERT INTO streetname VALUES('powatan'); + INSERT INTO streetname VALUES('prairie valley'); + INSERT INTO streetname VALUES('prescott'); + INSERT INTO streetname VALUES('presmann'); + INSERT INTO streetname VALUES('prestigious'); + INSERT INTO streetname VALUES('princess'); + INSERT INTO streetname VALUES('prosperity'); + INSERT INTO streetname VALUES('prosperity church'); + INSERT INTO streetname VALUES('prosperity commons'); + INSERT INTO streetname VALUES('prosperity park'); + INSERT INTO streetname VALUES('prosperity point'); + INSERT INTO streetname VALUES('prosperity ridge'); + INSERT INTO streetname VALUES('prosperity view'); + INSERT INTO streetname VALUES('purple finch'); + INSERT INTO streetname VALUES('quail'); + INSERT INTO streetname VALUES('queensbury'); + INSERT INTO streetname VALUES('quinn'); + INSERT INTO streetname VALUES('racine'); + INSERT INTO streetname VALUES('radbourne'); + INSERT INTO streetname VALUES('raddington'); + INSERT INTO streetname VALUES('raku'); + INSERT INTO streetname VALUES('rancliffe'); + INSERT INTO streetname VALUES('ravencrest'); + INSERT INTO streetname VALUES('reames'); + INSERT INTO streetname VALUES('rebecca run'); + INSERT INTO streetname VALUES('red bluff'); + INSERT INTO streetname VALUES('red clay'); + INSERT INTO streetname VALUES('red clover'); + INSERT INTO streetname VALUES('red rose'); + INSERT INTO streetname VALUES('red shed'); + INSERT INTO streetname VALUES('red tail'); + INSERT INTO streetname VALUES('redbridge'); + INSERT INTO streetname VALUES('redstart'); + INSERT INTO streetname VALUES('redstone view'); + INSERT INTO streetname VALUES('reedmont'); + INSERT INTO streetname VALUES('reeves'); + INSERT INTO streetname VALUES('regal'); + INSERT INTO streetname VALUES('reinbeck'); + INSERT INTO streetname VALUES('retriever'); + INSERT INTO streetname VALUES('ribbonwalk'); + INSERT INTO streetname VALUES('richardson park'); + INSERT INTO streetname VALUES('richfield'); + INSERT INTO streetname VALUES('riddings'); + INSERT INTO streetname VALUES('ridge'); + INSERT INTO streetname VALUES('ridge cliff'); + INSERT INTO streetname VALUES('ridge path'); + INSERT INTO streetname VALUES('ridge peak'); + INSERT INTO streetname VALUES('ridgefield'); + INSERT INTO streetname VALUES('ridgeline'); + INSERT INTO streetname VALUES('ridgeview commons'); + INSERT INTO streetname VALUES('riley'); + INSERT INTO streetname VALUES('riley woods'); + INSERT INTO streetname VALUES('rillet'); + INSERT INTO streetname VALUES('rindle'); + INSERT INTO streetname VALUES('rivendell'); + INSERT INTO streetname VALUES('robin'); + INSERT INTO streetname VALUES('robins nest'); + INSERT INTO streetname VALUES('robur'); + INSERT INTO streetname VALUES('robyns glen'); + INSERT INTO streetname VALUES('rock stream'); + INSERT INTO streetname VALUES('rockwell'); + INSERT INTO streetname VALUES('rockwell church'); + INSERT INTO streetname VALUES('rocky brook'); + INSERT INTO streetname VALUES('rocky ford club'); + INSERT INTO streetname VALUES('rotary'); + INSERT INTO streetname VALUES('rouda'); + INSERT INTO streetname VALUES('royal bluff'); + INSERT INTO streetname VALUES('royal celadon'); + INSERT INTO streetname VALUES('rubin lura'); + INSERT INTO streetname VALUES('runswyck'); + INSERT INTO streetname VALUES('ruth ferrell'); + INSERT INTO streetname VALUES('ruth polk'); + INSERT INTO streetname VALUES('ryan jay'); + INSERT INTO streetname VALUES('sackett'); + INSERT INTO streetname VALUES('saddle pace'); + INSERT INTO streetname VALUES('saddle run'); + INSERT INTO streetname VALUES('saddle trail'); + INSERT INTO streetname VALUES('saguaro'); + INSERT INTO streetname VALUES('saint audrey'); + INSERT INTO streetname VALUES('saint bernard'); + INSERT INTO streetname VALUES('saint frances'); + INSERT INTO streetname VALUES('sam roper'); + INSERT INTO streetname VALUES('samara'); + INSERT INTO streetname VALUES('sanders creek'); + INSERT INTO streetname VALUES('saquache'); + INSERT INTO streetname VALUES('sarnia'); + INSERT INTO streetname VALUES('savannah springs'); + INSERT INTO streetname VALUES('sawgrass ridge'); + INSERT INTO streetname VALUES('saxonbury'); + INSERT INTO streetname VALUES('scotch moss'); + INSERT INTO streetname VALUES('seasons'); + INSERT INTO streetname VALUES('serenity'); + INSERT INTO streetname VALUES('seths'); + INSERT INTO streetname VALUES('shadow lawn'); + INSERT INTO streetname VALUES('shadow oaks'); + INSERT INTO streetname VALUES('shadow pine'); + INSERT INTO streetname VALUES('shadyside'); + INSERT INTO streetname VALUES('shallow oak'); + INSERT INTO streetname VALUES('shelley'); + INSERT INTO streetname VALUES('shining oak'); + INSERT INTO streetname VALUES('ship'); + INSERT INTO streetname VALUES('shore haven'); + INSERT INTO streetname VALUES('shuman'); + INSERT INTO streetname VALUES('sidney'); + INSERT INTO streetname VALUES('silver birch'); + INSERT INTO streetname VALUES('silvermere'); + INSERT INTO streetname VALUES('simonton'); + INSERT INTO streetname VALUES('singing hills'); + INSERT INTO streetname VALUES('singing oak'); + INSERT INTO streetname VALUES('sipes'); + INSERT INTO streetname VALUES('six point'); + INSERT INTO streetname VALUES('skycrest'); + INSERT INTO streetname VALUES('skyline'); + INSERT INTO streetname VALUES('small'); + INSERT INTO streetname VALUES('smith corners'); + INSERT INTO streetname VALUES('smithwood'); + INSERT INTO streetname VALUES('snow hill'); + INSERT INTO streetname VALUES('soapstone'); + INSERT INTO streetname VALUES('sobeck'); + INSERT INTO streetname VALUES('socata'); + INSERT INTO streetname VALUES('solace'); + INSERT INTO streetname VALUES('solway'); + INSERT INTO streetname VALUES('song sparrow'); + INSERT INTO streetname VALUES('sorrento'); + INSERT INTO streetname VALUES('spector'); + INSERT INTO streetname VALUES('spin drift'); + INSERT INTO streetname VALUES('spring crest'); + INSERT INTO streetname VALUES('spring lee'); + INSERT INTO streetname VALUES('spring park'); + INSERT INTO streetname VALUES('spring terrace'); + INSERT INTO streetname VALUES('spring trace'); + INSERT INTO streetname VALUES('springhaven'); + INSERT INTO streetname VALUES('squirrel trail'); + INSERT INTO streetname VALUES('stardust'); + INSERT INTO streetname VALUES('stargaze'); + INSERT INTO streetname VALUES('starita'); + INSERT INTO streetname VALUES('starmount'); + INSERT INTO streetname VALUES('statesville'); + INSERT INTO streetname VALUES('steed'); + INSERT INTO streetname VALUES('steelewood'); + INSERT INTO streetname VALUES('steepleglen'); + INSERT INTO streetname VALUES('stephens farm'); + INSERT INTO streetname VALUES('stewarton'); + INSERT INTO streetname VALUES('stone park'); + INSERT INTO streetname VALUES('stonebrook'); + INSERT INTO streetname VALUES('stonefield'); + INSERT INTO streetname VALUES('stoneglen'); + INSERT INTO streetname VALUES('stonemarsh'); + INSERT INTO streetname VALUES('stoney garden'); + INSERT INTO streetname VALUES('stoney run'); + INSERT INTO streetname VALUES('stoney valley'); + INSERT INTO streetname VALUES('stoneykirk'); + INSERT INTO streetname VALUES('stream bank'); + INSERT INTO streetname VALUES('stream ridge'); + INSERT INTO streetname VALUES('suburban'); + INSERT INTO streetname VALUES('suffield'); + INSERT INTO streetname VALUES('sugar creek'); + INSERT INTO streetname VALUES('sugarberry'); + INSERT INTO streetname VALUES('sugarstone'); + INSERT INTO streetname VALUES('summer creek'); + INSERT INTO streetname VALUES('summer valley'); + INSERT INTO streetname VALUES('summercrest'); + INSERT INTO streetname VALUES('summercroft'); + INSERT INTO streetname VALUES('summerford'); + INSERT INTO streetname VALUES('summergold'); + INSERT INTO streetname VALUES('sunbeam'); + INSERT INTO streetname VALUES('sunbridge'); + INSERT INTO streetname VALUES('sunpath'); + INSERT INTO streetname VALUES('sunset'); + INSERT INTO streetname VALUES('sunset ridge'); + INSERT INTO streetname VALUES('sunstone'); + INSERT INTO streetname VALUES('suntrace'); + INSERT INTO streetname VALUES('sunwalk'); + INSERT INTO streetname VALUES('sutters hill'); + INSERT INTO streetname VALUES('suttonview'); + INSERT INTO streetname VALUES('swallow tail'); + INSERT INTO streetname VALUES('swanston'); + INSERT INTO streetname VALUES('sweet grove'); + INSERT INTO streetname VALUES('sweet rose'); + INSERT INTO streetname VALUES('sweetbriar ridge'); + INSERT INTO streetname VALUES('sweetfield'); + INSERT INTO streetname VALUES('sydney overlook'); + INSERT INTO streetname VALUES('sylvan'); + INSERT INTO streetname VALUES('symphony woods'); + INSERT INTO streetname VALUES('tallia'); + INSERT INTO streetname VALUES('tallu'); + INSERT INTO streetname VALUES('talwyn'); + INSERT INTO streetname VALUES('tanager'); + INSERT INTO streetname VALUES('tanager park'); + INSERT INTO streetname VALUES('tangley'); + INSERT INTO streetname VALUES('taranasay'); + INSERT INTO streetname VALUES('tarby'); + INSERT INTO streetname VALUES('tarland'); + INSERT INTO streetname VALUES('tarpway'); + INSERT INTO streetname VALUES('tauten'); + INSERT INTO streetname VALUES('taymouth'); + INSERT INTO streetname VALUES('ten trees'); + INSERT INTO streetname VALUES('terrace view'); + INSERT INTO streetname VALUES('terrier'); + INSERT INTO streetname VALUES('tesh'); + INSERT INTO streetname VALUES('teton'); + INSERT INTO streetname VALUES('tewkesbury'); + INSERT INTO streetname VALUES('thelema'); + INSERT INTO streetname VALUES('thistle bloom'); + INSERT INTO streetname VALUES('thistledown'); + INSERT INTO streetname VALUES('thomas ridge'); + INSERT INTO streetname VALUES('thornbrook'); + INSERT INTO streetname VALUES('tifton grass'); + INSERT INTO streetname VALUES('tigerton'); + INSERT INTO streetname VALUES('tomsie efird'); + INSERT INTO streetname VALUES('tor'); + INSERT INTO streetname VALUES('torphin'); + INSERT INTO streetname VALUES('torrence'); + INSERT INTO streetname VALUES('towering pine'); + INSERT INTO streetname VALUES('towhee'); + INSERT INTO streetname VALUES('toxaway'); + INSERT INTO streetname VALUES('tracy glenn'); + INSERT INTO streetname VALUES('tradition view'); + INSERT INTO streetname VALUES('trailer'); + INSERT INTO streetname VALUES('transport'); + INSERT INTO streetname VALUES('trehurst'); + INSERT INTO streetname VALUES('trexler'); + INSERT INTO streetname VALUES('trillium fields'); + INSERT INTO streetname VALUES('trimbach'); + INSERT INTO streetname VALUES('tucker'); + INSERT INTO streetname VALUES('tullamore'); + INSERT INTO streetname VALUES('tullock creek'); + INSERT INTO streetname VALUES('tunston'); + INSERT INTO streetname VALUES('tupelo'); + INSERT INTO streetname VALUES('turnabout'); + INSERT INTO streetname VALUES('turney'); + INSERT INTO streetname VALUES('turtle cross'); + INSERT INTO streetname VALUES('turtleback'); + INSERT INTO streetname VALUES('twelvestone'); + INSERT INTO streetname VALUES('twin'); + INSERT INTO streetname VALUES('twin brook'); + INSERT INTO streetname VALUES('twin lakes'); + INSERT INTO streetname VALUES('twisted pine'); + INSERT INTO streetname VALUES('tyler finley'); + INSERT INTO streetname VALUES('university station'); + INSERT INTO streetname VALUES('uphill'); + INSERT INTO streetname VALUES('valeview'); + INSERT INTO streetname VALUES('valhalla'); + INSERT INTO streetname VALUES('van'); + INSERT INTO streetname VALUES('vance davis'); + INSERT INTO streetname VALUES('vanhoy'); + INSERT INTO streetname VALUES('veckman'); + INSERT INTO streetname VALUES('victoria'); + INSERT INTO streetname VALUES('victory'); + INSERT INTO streetname VALUES('village glen'); + INSERT INTO streetname VALUES('vireo'); + INSERT INTO streetname VALUES('viscount'); + INSERT INTO streetname VALUES('voeltz'); + INSERT INTO streetname VALUES('wade e morgan'); + INSERT INTO streetname VALUES('wake'); + INSERT INTO streetname VALUES('wales'); + INSERT INTO streetname VALUES('wallace ridge'); + INSERT INTO streetname VALUES('waltham'); + INSERT INTO streetname VALUES('wanamassa'); + INSERT INTO streetname VALUES('warbler wood'); + INSERT INTO streetname VALUES('washington'); + INSERT INTO streetname VALUES('water'); + INSERT INTO streetname VALUES('waterelm'); + INSERT INTO streetname VALUES('waterford hills'); + INSERT INTO streetname VALUES('waterford valley'); + INSERT INTO streetname VALUES('waterloo'); + INSERT INTO streetname VALUES('waterton leas'); + INSERT INTO streetname VALUES('waverly lynn'); + INSERT INTO streetname VALUES('waverlyglen'); + INSERT INTO streetname VALUES('wayside'); + INSERT INTO streetname VALUES('westbury lake'); + INSERT INTO streetname VALUES('westray'); + INSERT INTO streetname VALUES('whistlers chase'); + INSERT INTO streetname VALUES('whistley green'); + INSERT INTO streetname VALUES('whistling oak'); + INSERT INTO streetname VALUES('whitcomb'); + INSERT INTO streetname VALUES('white aspen'); + INSERT INTO streetname VALUES('white cascade'); + INSERT INTO streetname VALUES('white mist'); + INSERT INTO streetname VALUES('white rock'); + INSERT INTO streetname VALUES('white stag'); + INSERT INTO streetname VALUES('whitegate'); + INSERT INTO streetname VALUES('whitehill'); + INSERT INTO streetname VALUES('whitetail'); + INSERT INTO streetname VALUES('whitewood'); + INSERT INTO streetname VALUES('wilburn park'); + INSERT INTO streetname VALUES('wild garden'); + INSERT INTO streetname VALUES('wild rose'); + INSERT INTO streetname VALUES('wilkins terrace'); + INSERT INTO streetname VALUES('william ficklen'); + INSERT INTO streetname VALUES('wiltshire ridge'); + INSERT INTO streetname VALUES('windchase'); + INSERT INTO streetname VALUES('winding jordan'); + INSERT INTO streetname VALUES('windy meadow'); + INSERT INTO streetname VALUES('winghaven'); + INSERT INTO streetname VALUES('wingmont'); + INSERT INTO streetname VALUES('winslow'); + INSERT INTO streetname VALUES('winter pine'); + INSERT INTO streetname VALUES('winter view'); + INSERT INTO streetname VALUES('wolf creek'); + INSERT INTO streetname VALUES('wondering oak'); + INSERT INTO streetname VALUES('woodard'); + INSERT INTO streetname VALUES('woodfire'); + INSERT INTO streetname VALUES('woodland commons'); + INSERT INTO streetname VALUES('woodland hills'); + INSERT INTO streetname VALUES('woodnotch'); + INSERT INTO streetname VALUES('woodstone'); + INSERT INTO streetname VALUES('worsley'); + INSERT INTO streetname VALUES('wren creek'); + INSERT INTO streetname VALUES('wrens nest'); + INSERT INTO streetname VALUES('wrexham'); + INSERT INTO streetname VALUES('wt harris'); + INSERT INTO streetname VALUES('wylie meadow'); + INSERT INTO streetname VALUES('wynborough'); + INSERT INTO streetname VALUES('wynbrook'); + INSERT INTO streetname VALUES('wyndham hill'); + INSERT INTO streetname VALUES('yandem'); + INSERT INTO streetname VALUES('yellow rose'); + INSERT INTO streetname VALUES('yellow spaniel'); + INSERT INTO streetname VALUES('yorkford'); + INSERT INTO streetname VALUES('ziegler'); + INSERT INTO streetname VALUES('zion renaissance'); + + SELECT count(*) FROM streetname; + } +} {1228} + +do_test fuzzer1-2.1 { + execsql { + SELECT n, distance FROM f2, streetname + WHERE f2.word MATCH 'wersley' + AND f2.distance<=150 + AND f2.word=streetname.n + } +} {worsley 37} +do_test fuzzer1-2.2 { + execsql { + SELECT n, distance FROM f2, streetname + WHERE f2.word MATCH 'testledown' + AND f2.distance<=150 + AND f2.word=streetname.n + } +} {thistledown 103} +do_test fuzzer1-2.3 { + execsql { + SELECT DISTINCT streetname.n FROM f2, streetname + WHERE f2.word MATCH 'tayle' + AND f2.distance<=200 + AND streetname.n>=f2.word AND streetname.n<=(f2.word || x'F7BFBFBF') + } +} {steelewood tallia tallu talwyn taymouth thelema trailer {tyler finley}} + finish_test diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100755 new mode 100644 From 8689bc308f3b327625856aa5ba55e332e9c44a89 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2011 20:54:38 +0000 Subject: [PATCH 19/31] Fix up the Makefile.in so that the configuration script works for "make test". FossilOrigin-Name: 2e03830c1e1b05f7b22f9fe553ae708b65a4e942 --- Makefile.in | 1 + manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile.in b/Makefile.in index 2ee36dec43..2c134a27f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -372,6 +372,7 @@ TESTSRC = \ $(TOP)/src/test_schema.c \ $(TOP)/src/test_server.c \ $(TOP)/src/test_superlock.c \ + $(TOP)/src/test_syscall.c \ $(TOP)/src/test_stat.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ diff --git a/manifest b/manifest index 6bfc30d59a..684fa4d067 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Merge\sthe\sword-fuzzer\sbranch\sinto\strunk. -D 2011-04-01T20:47:27.009 +C Fix\sup\sthe\sMakefile.in\sso\sthat\sthe\sconfiguration\sscript\sworks\sfor\s\n"make\stest". +D 2011-04-01T20:54:38.434 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 6c96e694f446500449f683070b906de9fce17b88 +F Makefile.in e40cb0124e5a71e3ec545e828bb795dd46da5fcb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 @@ -925,7 +925,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P b477852f82c1fddbda61fad83d55055ad8503dda a6a81d4fdafabba514e8f8e1958d6132b3850772 -R 8fa020ba89288daa4e980326f651b43c +P f77609d44194ee8871b3fb281ea6b90a9182f69f +R d38929f39188d1b3fa8897057287e84b U drh -Z f9a8b03fbe76a0642382439288b4d943 +Z ca70e73356c79c1f0f3c6edc9c65ce94 diff --git a/manifest.uuid b/manifest.uuid index c526826d6d..5c5ee84be7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f77609d44194ee8871b3fb281ea6b90a9182f69f \ No newline at end of file +2e03830c1e1b05f7b22f9fe553ae708b65a4e942 \ No newline at end of file From 70586beb3dbd344d4b67b9d8d2d268ac7d50149c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 1 Apr 2011 23:49:44 +0000 Subject: [PATCH 20/31] Add the "wholenumber" virtual table module to the test suite - useful in populating tables with many rows of content prior to a test. FossilOrigin-Name: 975dff155bd9db42f2b6855b24c861852bb7a201 --- Makefile.in | 1 + main.mk | 1 + manifest | 21 +-- manifest.uuid | 2 +- src/tclsqlite.c | 2 + src/test_wholenumber.c | 311 +++++++++++++++++++++++++++++++++++++++++ test/analyze7.test | 16 +-- test/memdb.test | 12 +- 8 files changed, 334 insertions(+), 32 deletions(-) create mode 100644 src/test_wholenumber.c diff --git a/Makefile.in b/Makefile.in index 2c134a27f7..f3239f3d79 100644 --- a/Makefile.in +++ b/Makefile.in @@ -377,6 +377,7 @@ TESTSRC = \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ + $(TOP)/src/test_wholenumber.c \ $(TOP)/src/test_wsd.c # Source code to the library files needed by the test fixture diff --git a/main.mk b/main.mk index 8728eeb962..e1df7a77f1 100644 --- a/main.mk +++ b/main.mk @@ -258,6 +258,7 @@ TESTSRC = \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ + $(TOP)/src/test_wholenumber.c \ $(TOP)/src/test_wsd.c #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c diff --git a/manifest b/manifest index 684fa4d067..8ecad8f49c 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Fix\sup\sthe\sMakefile.in\sso\sthat\sthe\sconfiguration\sscript\sworks\sfor\s\n"make\stest". -D 2011-04-01T20:54:38.434 +C Add\sthe\s"wholenumber"\svirtual\stable\smodule\sto\sthe\stest\ssuite\s-\suseful\sin\npopulating\stables\swith\smany\srows\sof\scontent\sprior\sto\sa\stest. +D 2011-04-01T23:49:44.644 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in e40cb0124e5a71e3ec545e828bb795dd46da5fcb +F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 @@ -101,7 +101,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 078e1b601071cc50b4b6ccac9faece349ead1c39 +F main.mk bd4e376deea4704b2bd9c77a4e6f0fa3de25c495 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -184,7 +184,7 @@ F src/sqliteInt.h f8f1d00a22c98fd3f2fbc94da74eeb880879f89f F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c e8c3bc4662975cf9a8e0280b1703a3cf427f9831 +F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b F src/test1.c 9ca440e80e16e53920904a0a5ac7feffb9b2c9a1 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc @@ -227,6 +227,7 @@ F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0 F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86 F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1 +F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c ec4813709e990a169b6923293e839fa5dfd64282 @@ -261,7 +262,7 @@ F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290 -F test/analyze7.test 8095fed183e1fb999c1b1c4a1606cec1bcb13d1f +F test/analyze7.test 550c38ac6823f300bbe836b4d6db5d1492806046 F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e @@ -567,7 +568,7 @@ F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9 F test/malloc_common.tcl 50d0ed21eed0ae9548b58935bd29ac89a05a54fa F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f -F test/memdb.test 0825155b2290e900264daaaf0334b6dfe69ea498 +F test/memdb.test 7db5c2d98133ce95711ac36700a4a1e9f0b0692b F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10 F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc @@ -925,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f77609d44194ee8871b3fb281ea6b90a9182f69f -R d38929f39188d1b3fa8897057287e84b +P 2e03830c1e1b05f7b22f9fe553ae708b65a4e942 +R 573ca184e9da16256a7f531dba0f1340 U drh -Z ca70e73356c79c1f0f3c6edc9c65ce94 +Z 1ec9b30671b78237d3db767735d384c0 diff --git a/manifest.uuid b/manifest.uuid index 5c5ee84be7..2d1802e133 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e03830c1e1b05f7b22f9fe553ae708b65a4e942 \ No newline at end of file +975dff155bd9db42f2b6855b24c861852bb7a201 \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 79ee1946b0..575651d7e5 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3583,6 +3583,7 @@ static void init_all(Tcl_Interp *interp){ extern int SqliteSuperlock_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*); extern int Sqlitetestfuzzer_Init(Tcl_Interp*); + extern int Sqlitetestwholenumber_Init(Tcl_Interp*); #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); @@ -3622,6 +3623,7 @@ static void init_all(Tcl_Interp *interp){ SqliteSuperlock_Init(interp); SqlitetestSyscall_Init(interp); Sqlitetestfuzzer_Init(interp); + Sqlitetestwholenumber_Init(interp); Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0); diff --git a/src/test_wholenumber.c b/src/test_wholenumber.c new file mode 100644 index 0000000000..150dc95ac4 --- /dev/null +++ b/src/test_wholenumber.c @@ -0,0 +1,311 @@ +/* +** 2011 April 02 +** +** 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 a virtual table that returns the whole numbers +** between 1 and 4294967295, inclusive. +** +** Example: +** +** CREATE VIRTUAL TABLE nums USING wholenumber; +** SELECT value FROM nums WHERE value<10; +** +** Results in: +** +** 1 2 3 4 5 6 7 8 9 +*/ +#include "sqlite3.h" +#include +#include + +#ifndef SQLITE_OMIT_VIRTUALTABLE + + +/* A wholenumber cursor object */ +typedef struct wholenumber_cursor wholenumber_cursor; +struct wholenumber_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + unsigned iValue; /* Current value */ + unsigned mxValue; /* Maximum value */ +}; + +/* Methods for the wholenumber module */ +static int wholenumberConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + sqlite3_declare_vtab(db, "CREATE TABLE x(value)"); + memset(pNew, 0, sizeof(*pNew)); + return SQLITE_OK; +} +/* Note that for this virtual table, the xCreate and xConnect +** methods are identical. */ + +static int wholenumberDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} +/* The xDisconnect and xDestroy methods are also the same */ + + +/* +** Open a new wholenumber cursor. +*/ +static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + wholenumber_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Close a wholenumber cursor. +*/ +static int wholenumberClose(sqlite3_vtab_cursor *cur){ + sqlite3_free(cur); + return SQLITE_OK; +} + + +/* +** Advance a cursor to its next row of output +*/ +static int wholenumberNext(sqlite3_vtab_cursor *cur){ + wholenumber_cursor *pCur = (wholenumber_cursor*)cur; + pCur->iValue++; + return SQLITE_OK; +} + +/* +** Return the value associated with a wholenumber. +*/ +static int wholenumberColumn( + sqlite3_vtab_cursor *cur, + sqlite3_context *ctx, + int i +){ + wholenumber_cursor *pCur = (wholenumber_cursor*)cur; + sqlite3_result_int64(ctx, pCur->iValue); + return SQLITE_OK; +} + +/* +** The rowid. +*/ +static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + wholenumber_cursor *pCur = (wholenumber_cursor*)cur; + *pRowid = pCur->iValue; + return SQLITE_OK; +} + +/* +** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal +** that the cursor has nothing more to output. +*/ +static int wholenumberEof(sqlite3_vtab_cursor *cur){ + wholenumber_cursor *pCur = (wholenumber_cursor*)cur; + return pCur->iValue>pCur->mxValue || pCur->iValue==0; +} + +/* +** Called to "rewind" a cursor back to the beginning so that +** it starts its output over again. Always called at least once +** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call. +** +** idxNum Constraints +** ------ --------------------- +** 0 (none) +** 1 value > $argv0 +** 2 value >= $argv0 +** 4 value < $argv0 +** 8 value <= $argv0 +** +** 5 value > $argv0 AND value < $argv1 +** 6 value >= $argv0 AND value < $argv1 +** 9 value > $argv0 AND value <= $argv1 +** 10 value >= $argv0 AND value <= $argv1 +*/ +static int wholenumberFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor; + sqlite3_int64 v; + int i = 0; + pCur->iValue = 1; + pCur->mxValue = 0xffffffff; /* 4294967295 */ + if( idxNum & 3 ){ + v = sqlite3_value_int64(argv[0]) + (idxNum&1); + if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v; + i++; + } + if( idxNum & 12 ){ + v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1); + if( v>=pCur->iValue && vmxValue ) pCur->mxValue = v; + } + return SQLITE_OK; +} + +/* +** Search for terms of these forms: +** +** (1) value > $value +** (2) value >= $value +** (4) value < $value +** (8) value <= $value +** +** idxNum is an ORed combination of 1 or 2 with 4 or 8. +*/ +static int wholenumberBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; + int idxNum = 0; + int argvIdx = 1; + int ltIdx = -1; + int gtIdx = -1; + const struct sqlite3_index_constraint *pConstraint; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){ + idxNum |= 1; + ltIdx = i; + } + if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){ + idxNum |= 2; + ltIdx = i; + } + if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){ + idxNum |= 4; + gtIdx = i; + } + if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){ + idxNum |= 8; + gtIdx = i; + } + } + pIdxInfo->idxNum = idxNum; + if( ltIdx>=0 ){ + pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++; + pIdxInfo->aConstraintUsage[ltIdx].omit = 1; + } + if( gtIdx>=0 ){ + pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx; + pIdxInfo->aConstraintUsage[gtIdx].omit = 1; + } + if( pIdxInfo->nOrderBy==1 + && pIdxInfo->aOrderBy[0].desc==0 + ){ + pIdxInfo->orderByConsumed = 1; + } + pIdxInfo->estimatedCost = (double)1; + return SQLITE_OK; +} + +/* +** A virtual table module that provides read-only access to a +** Tcl global variable namespace. +*/ +static sqlite3_module wholenumberModule = { + 0, /* iVersion */ + wholenumberConnect, + wholenumberConnect, + wholenumberBestIndex, + wholenumberDisconnect, + wholenumberDisconnect, + wholenumberOpen, /* xOpen - open a cursor */ + wholenumberClose, /* xClose - close a cursor */ + wholenumberFilter, /* xFilter - configure scan constraints */ + wholenumberNext, /* xNext - advance a cursor */ + wholenumberEof, /* xEof - check for end of scan */ + wholenumberColumn, /* xColumn - read data */ + wholenumberRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + +/* +** Register the wholenumber virtual table +*/ +int wholenumber_register(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0); +#endif + return rc; +} + +#ifdef SQLITE_TEST +#include +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the echo virtual table module. +*/ +static int register_wholenumber_module( + 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; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + wholenumber_register(db); + return TCL_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetestwholenumber_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "register_wholenumber_module", register_wholenumber_module, 0 }, + }; + int i; + for(i=0; i Date: Sat, 2 Apr 2011 06:44:38 +0000 Subject: [PATCH 21/31] Fix additional test cases so that they work with DEFAULT_AUTOVACUUM. FossilOrigin-Name: 139bc5655ed1d0fd1b7ca86d05a998fcc5fbc18e --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/pagerfault3.test | 1 + test/walfault.test | 2 ++ 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8ecad8f49c..1cdf72d25d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"wholenumber"\svirtual\stable\smodule\sto\sthe\stest\ssuite\s-\suseful\sin\npopulating\stables\swith\smany\srows\sof\scontent\sprior\sto\sa\stest. -D 2011-04-01T23:49:44.644 +C Fix\sadditional\stest\scases\sso\sthat\sthey\swork\swith\sDEFAULT_AUTOVACUUM. +D 2011-04-02T06:44:38.855 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -600,7 +600,7 @@ F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f F test/pagerfault.test 9de4d3e0c59970b4c6cb8dac511fa242f335d8a7 F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401 -F test/pagerfault3.test 9b413f48a3e9a9a8c26968118f8db19fd7bfb8c7 +F test/pagerfault3.test f16e2efcb5fc9996d1356f7cbc44c998318ae1d7 F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 @@ -872,7 +872,7 @@ F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0 F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5 F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142 -F test/walfault.test bf3808895f3b0751f6b0dbf52bb6d2e3a7b76a9d +F test/walfault.test 58fce626359c9376fe35101b5c0f2df8040aa839 F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483 F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2e03830c1e1b05f7b22f9fe553ae708b65a4e942 -R 573ca184e9da16256a7f531dba0f1340 -U drh -Z 1ec9b30671b78237d3db767735d384c0 +P 975dff155bd9db42f2b6855b24c861852bb7a201 +R fe70661f0564d3a2ebc3b072a895ef40 +U dan +Z b324e5f3ad19924d1e70c5c53376688b diff --git a/manifest.uuid b/manifest.uuid index 2d1802e133..b26ab516c7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -975dff155bd9db42f2b6855b24c861852bb7a201 \ No newline at end of file +139bc5655ed1d0fd1b7ca86d05a998fcc5fbc18e \ No newline at end of file diff --git a/test/pagerfault3.test b/test/pagerfault3.test index 6f63b83f93..3d192e6d43 100644 --- a/test/pagerfault3.test +++ b/test/pagerfault3.test @@ -26,6 +26,7 @@ if {[permutation] == "inmemory_journal"} { # do_test pagerfault3-pre1 { execsql { + PRAGMA auto_vacuum = 0; PRAGMA page_size = 2048; CREATE TABLE t1(x); INSERT INTO t1 VALUES(randomblob(1200)); diff --git a/test/walfault.test b/test/walfault.test index 20c981bb5a..3a90f9c693 100644 --- a/test/walfault.test +++ b/test/walfault.test @@ -133,6 +133,7 @@ if {[permutation] != "inmemory_journal"} { faultsim_restore_and_reopen } -body { execsql { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES('a', 'b'); @@ -523,6 +524,7 @@ do_faultsim_test walfault-13.3 -prep { do_test walfault-14-pre { faultsim_delete_and_reopen execsql { + PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; BEGIN; CREATE TABLE abc(a PRIMARY KEY); From 82346d9873e29114ff184cb25130821763502b86 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 2 Apr 2011 09:25:14 +0000 Subject: [PATCH 22/31] Do not attempt to run tests that use the 'wholenumber' virtual table if the build does not support virtual tables. FossilOrigin-Name: 20afd81a4cf4d23962ec841bbd375f36a5156fb6 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/analyze7.test | 2 +- test/memdb.test | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1cdf72d25d..04c1085d80 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sadditional\stest\scases\sso\sthat\sthey\swork\swith\sDEFAULT_AUTOVACUUM. -D 2011-04-02T06:44:38.855 +C Do\snot\sattempt\sto\srun\stests\sthat\suse\sthe\s'wholenumber'\svirtual\stable\sif\sthe\sbuild\sdoes\snot\ssupport\svirtual\stables. +D 2011-04-02T09:25:14.909 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -262,7 +262,7 @@ F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 F test/analyze5.test adc89b92fc9fee5ca1cb0bc8512f3206ad0fe5aa F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290 -F test/analyze7.test 550c38ac6823f300bbe836b4d6db5d1492806046 +F test/analyze7.test 9cbca440bebc5142a875ad23947797ff52f7b37c F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e @@ -568,7 +568,7 @@ F test/mallocK.test d79968641d1b70d88f6c01bdb9a7eb4a55582cc9 F test/malloc_common.tcl 50d0ed21eed0ae9548b58935bd29ac89a05a54fa F test/manydb.test b3d3bc4c25657e7f68d157f031eb4db7b3df0d3c F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f -F test/memdb.test 7db5c2d98133ce95711ac36700a4a1e9f0b0692b +F test/memdb.test 708a028d6d373e5b3842e4bdc8ba80998c9a4da6 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 679db68394a5692791737b150852173b3e2fea10 F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 975dff155bd9db42f2b6855b24c861852bb7a201 -R fe70661f0564d3a2ebc3b072a895ef40 +P 139bc5655ed1d0fd1b7ca86d05a998fcc5fbc18e +R 85c1ab3db7c73393d878faa825bb79d8 U dan -Z b324e5f3ad19924d1e70c5c53376688b +Z 27401d3cc561174a4c3aaa99ccf5b680 diff --git a/manifest.uuid b/manifest.uuid index b26ab516c7..201bc67d24 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -139bc5655ed1d0fd1b7ca86d05a998fcc5fbc18e \ No newline at end of file +20afd81a4cf4d23962ec841bbd375f36a5156fb6 \ No newline at end of file diff --git a/test/analyze7.test b/test/analyze7.test index ede5cf57e0..a796ab78af 100644 --- a/test/analyze7.test +++ b/test/analyze7.test @@ -18,7 +18,7 @@ source $testdir/tester.tcl # There is nothing to test if ANALYZE is disable for this build. # -ifcapable {!analyze} { +ifcapable {!analyze||!vtab} { finish_test return } diff --git a/test/memdb.test b/test/memdb.test index 86ac863f78..1da3d7c58b 100644 --- a/test/memdb.test +++ b/test/memdb.test @@ -363,7 +363,7 @@ do_test memdb-6.15 { } } {} -ifcapable subquery { +ifcapable subquery&&vtab { do_test memdb-7.1 { register_wholenumber_module db execsql { From 6c15487b7edf747b7b08cf6eb311f503adb0cd6a Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 2 Apr 2011 09:44:43 +0000 Subject: [PATCH 23/31] Fix a race condition in OP_ParseSchema. FossilOrigin-Name: 71a799b02a3b3cf2e12758dea29fd2465bbec3e1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 31 +++++++++++++++++-------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 04c1085d80..8411b2239f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sattempt\sto\srun\stests\sthat\suse\sthe\s'wholenumber'\svirtual\stable\sif\sthe\sbuild\sdoes\snot\ssupport\svirtual\stables. -D 2011-04-02T09:25:14.909 +C Fix\sa\srace\scondition\sin\sOP_ParseSchema. +D 2011-04-02T09:44:43 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -235,7 +235,7 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c e3f37ca0afdd72e883475e2a32a06167df2810d0 +F src/vdbe.c a45a6a0daf2161797d50b3b5b8a3e0e4debf2d2b F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h e1c6254641168507d25b46affb6dfb53c782f553 F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 139bc5655ed1d0fd1b7ca86d05a998fcc5fbc18e -R 85c1ab3db7c73393d878faa825bb79d8 +P 20afd81a4cf4d23962ec841bbd375f36a5156fb6 +R 25d34b3e2efbdd1c8e0ceadec6512306 U dan -Z 27401d3cc561174a4c3aaa99ccf5b680 +Z 659aea6fa897bf521b0a686e5d197299 diff --git a/manifest.uuid b/manifest.uuid index 201bc67d24..fa61c3c651 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -20afd81a4cf4d23962ec841bbd375f36a5156fb6 \ No newline at end of file +71a799b02a3b3cf2e12758dea29fd2465bbec3e1 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 43d132f1ba..ddf507ee9d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4625,23 +4625,26 @@ case OP_ParseSchema: { iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); - /* Although the mutex on the BtShared object that corresponds to - ** database iDb (the database containing the sqlite_master table - ** read by this instruction) is currently held, it is necessary to - ** obtain the mutexes on all attached databases before checking if - ** the schema of iDb is loaded. This is because, at the start of - ** the sqlite3_exec() call below, SQLite will invoke - ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the - ** iDb mutex may be temporarily released to avoid deadlock. If - ** this happens, then some other thread may delete the in-memory - ** schema of database iDb before the SQL statement runs. The schema - ** will not be reloaded becuase the db->init.busy flag is set. This - ** can result in a "no such table: sqlite_master" or "malformed - ** database schema" error being returned to the user. + /* When this opcode is invoked, it is guaranteed that the b-tree mutex + ** is held and the schema is loaded for database iDb. However, at the + ** start of the sqlite3_exec() call below, SQLite will invoke + ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the iDb + ** mutex may be temporarily released to avoid deadlock. If this happens, + ** then some other thread may delete the in-memory schema of database iDb + ** before the SQL statement runs. The schema will not be reloaded because + ** the db->init.busy flag is set. This can result in a "no such table: + ** sqlite_master" or "malformed database schema" error being returned to + ** the user. + ** + ** To avoid this, obtain all mutexes and check that no other thread has + ** deleted the schema before calling sqlite3_exec(). If we find that the + ** another thread has deleted the schema, there is no need to update it. + ** The updated schema will be loaded from disk when it is next required. */ assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); sqlite3BtreeEnterAll(db); - if( ALWAYS(DbHasProperty(db, iDb, DB_SchemaLoaded)) ){ + if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){ zMaster = SCHEMA_TABLE(iDb); initData.db = db; initData.iDb = pOp->p1; From 51438a79366ef6cff5a920930ab76de401b53812 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 2 Apr 2011 17:00:47 +0000 Subject: [PATCH 24/31] Avoid returning SQLITE_NOTFOUND when the unix xSetSystemCall interface is invoked with NULL passed as the second argument, even if all the default system calls are already installed. FossilOrigin-Name: 3b91eaaa0b3c25022332ba3d1a5651848fc5d84c --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/os_unix.c | 2 +- src/test_syscall.c | 33 ++++++++++++++++++++++++++------- test/oserror.test | 1 + test/syscall.test | 23 ++++++++++++++--------- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 8411b2239f..81aef14195 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\srace\scondition\sin\sOP_ParseSchema. -D 2011-04-02T09:44:43 +C Avoid\sreturning\sSQLITE_NOTFOUND\swhen\sthe\sunix\sxSetSystemCall\sinterface\sis\sinvoked\swith\sNULL\spassed\sas\sthe\ssecond\sargument,\seven\sif\sall\sthe\sdefault\ssystem\scalls\sare\salready\sinstalled. +D 2011-04-02T17:00:48 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -162,7 +162,7 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9 F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 2596fd2d5d0976c6c0c628d0c3c7c4e7a724f4cf -F src/os_unix.c a3b4cdf50a9c9be8b50dc4932354ab749962a07f +F src/os_unix.c 32414676594a0a26cfccd7e02656230a3406eee7 F src/os_win.c 24d72407a90551969744cf9bcbb1b4c72c5fa845 F src/pager.c 6aa906b60a59664ba58d3f746164bb010d407ce1 F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1 @@ -222,7 +222,7 @@ F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6 F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd -F src/test_syscall.c 61bb14684142a19c580a13b4dde680044d37e0f5 +F src/test_syscall.c 34ce1be806cd180e241bc688ae3762e5e7825bda F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0 F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86 @@ -594,7 +594,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/oserror.test 6c61c859cd94864cfd6af83e0549e2800238c413 +F test/oserror.test 0abf1b4a935aae329b95da27388d7ca61aaea6f0 F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f @@ -677,7 +677,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 -F test/syscall.test d1dae1fee88613cf763d97ad0038d867509e0c42 +F test/syscall.test b967e1f5405bb1c9e2e223dbf7d7cd35220589a3 F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 20afd81a4cf4d23962ec841bbd375f36a5156fb6 -R 25d34b3e2efbdd1c8e0ceadec6512306 +P 71a799b02a3b3cf2e12758dea29fd2465bbec3e1 +R 96ca391ad53fdccc5149ee67daf1eb80 U dan -Z 659aea6fa897bf521b0a686e5d197299 +Z 09bfa66b6aa34161ab06f7710f843391 diff --git a/manifest.uuid b/manifest.uuid index fa61c3c651..098e94575a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -71a799b02a3b3cf2e12758dea29fd2465bbec3e1 \ No newline at end of file +3b91eaaa0b3c25022332ba3d1a5651848fc5d84c \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index f04b6af273..67dd06fc1c 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -394,10 +394,10 @@ static int unixSetSystemCall( /* If no zName is given, restore all system calls to their default ** settings and return NULL */ + rc = SQLITE_OK; for(i=0; izName, -1)); + return TCL_OK; +} + static int test_syscall( void * clientData, Tcl_Interp *interp, @@ -609,13 +627,14 @@ static int test_syscall( const char *zName; Tcl_ObjCmdProc *xCmd; } aCmd[] = { - { "fault", test_syscall_fault }, - { "install", test_syscall_install }, - { "uninstall", test_syscall_uninstall }, - { "reset", test_syscall_reset }, - { "errno", test_syscall_errno }, - { "exists", test_syscall_exists }, - { "list", test_syscall_list }, + { "fault", test_syscall_fault }, + { "install", test_syscall_install }, + { "uninstall", test_syscall_uninstall }, + { "reset", test_syscall_reset }, + { "errno", test_syscall_errno }, + { "exists", test_syscall_exists }, + { "list", test_syscall_list }, + { "defaultvfs", test_syscall_defaultvfs }, { 0, 0 } }; int iCmd; diff --git a/test/oserror.test b/test/oserror.test index d1952a30dd..82a5d5f6ff 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -111,6 +111,7 @@ do_test 2.1.3 { } {} +test_syscall reset sqlite3_shutdown test_sqlite3_log sqlite3_initialize diff --git a/test/syscall.test b/test/syscall.test index 21295a59cf..95921bd35e 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -19,8 +19,12 @@ if {[llength [info commands test_syscall]]==0} { finish_test return } -set testprefix syscall +if {[test_syscall defaultvfs] != "unix"} { + finish_test + return +} +set testprefix syscall #------------------------------------------------------------------------- # Tests for the xSetSystemCall method. @@ -52,12 +56,14 @@ do_test 2.1.2 { test_syscall exists nosuchcall } 0 #------------------------------------------------------------------------- # Tests for the xNextSystemCall method. # -set syscall_list [list \ - open close access getcwd stat fstat ftruncate \ - fcntl read pread write pwrite fchmod \ -] -if {[test_syscall exists fallocate]} {lappend syscall_list fallocate} -do_test 3.1 { test_syscall list } $syscall_list +foreach s { + open close access getcwd stat fstat ftruncate + fcntl read pread write pwrite fchmod fallocate + pread64 pwrite64 +} { + if {[test_syscall exists $s]} {lappend syscall_list $s} +} +do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list] #------------------------------------------------------------------------- # This test verifies that if a call to open() fails and errno is set to @@ -245,6 +251,5 @@ foreach {tn hint size} { } $size } - - +test_syscall reset finish_test From 6412358526b0f2b80c55d7ab11482c752025ed0c Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 2 Apr 2011 20:01:02 +0000 Subject: [PATCH 25/31] Change the name of the "tAttachMask" datatype to "yDbMask". FossilOrigin-Name: 3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/build.c | 8 ++++---- src/sqliteInt.h | 12 +++++++----- src/vdbeInt.h | 2 +- src/vdbeaux.c | 4 ++-- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 81aef14195..927bd9ef71 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sreturning\sSQLITE_NOTFOUND\swhen\sthe\sunix\sxSetSystemCall\sinterface\sis\sinvoked\swith\sNULL\spassed\sas\sthe\ssecond\sargument,\seven\sif\sall\sthe\sdefault\ssystem\scalls\sare\salready\sinstalled. -D 2011-04-02T17:00:48 +C Change\sthe\sname\sof\sthe\s"tAttachMask"\sdatatype\sto\s"yDbMask". +D 2011-04-02T20:01:02.621 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,7 +124,7 @@ F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff F src/btree.c 2b9c81ff64da339a67dda4f94c0d763627be0b67 F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4 -F src/build.c 6c490fe14dedb094a202f559e3b29a276abffcf8 +F src/build.c 3a8c6c4b1e16798755d46e699b7fcc12b9f27b2b F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01 @@ -180,7 +180,7 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 9dc0b4bb59290c0a35256d278cab0f314987ad6a F src/sqlite.h.in e047f69a61d604d4f8be6cf1d1bdfc68be9ba7e5 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h f8f1d00a22c98fd3f2fbc94da74eeb880879f89f +F src/sqliteInt.h d45b0b1db417d5308e3bf9c8983aaf2d06e7cd36 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -237,9 +237,9 @@ F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f F src/vdbe.c a45a6a0daf2161797d50b3b5b8a3e0e4debf2d2b F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h e1c6254641168507d25b46affb6dfb53c782f553 +F src/vdbeInt.h 8ee9302ecc1036509956df8aceea6b0b5e0e231c F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 77921792f7ebae267490816deb6a9488f938fa85 +F src/vdbeaux.c 80ed78c8e1edf8918e0e404891d314aa01ccb095 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 71a799b02a3b3cf2e12758dea29fd2465bbec3e1 -R 96ca391ad53fdccc5149ee67daf1eb80 -U dan -Z 09bfa66b6aa34161ab06f7710f843391 +P 3b91eaaa0b3c25022332ba3d1a5651848fc5d84c +R e5d6d2ab5437a135179f043b3faf09c4 +U drh +Z cdbe2872c525d3ae3a361db4be775f20 diff --git a/manifest.uuid b/manifest.uuid index 098e94575a..6c4bffcf25 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3b91eaaa0b3c25022332ba3d1a5651848fc5d84c \ No newline at end of file +3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa \ No newline at end of file diff --git a/src/build.c b/src/build.c index bf3273fc84..b4528347d5 100644 --- a/src/build.c +++ b/src/build.c @@ -148,7 +148,7 @@ void sqlite3FinishCoding(Parse *pParse){ ** on each used database. */ if( pParse->cookieGoto>0 ){ - tAttachMask mask; + yDbMask mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ @@ -3444,12 +3444,12 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ } if( iDb>=0 ){ sqlite3 *db = pToplevel->db; - tAttachMask mask; + yDbMask mask; assert( iDbnDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbcookieMask & mask)==0 ){ pToplevel->cookieMask |= mask; pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; @@ -3476,7 +3476,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); sqlite3CodeVerifySchema(pParse, iDb); - pToplevel->writeMask |= ((tAttachMask)1)<writeMask |= ((yDbMask)1)<isMultiWrite |= setStatement; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0825af4cdf..ba5552dba4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2125,11 +2125,13 @@ struct TriggerPrg { TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ }; -/* Datatype for the bitmask of all attached databases */ +/* +** The yDbMask datatype for the bitmask of all attached databases. +*/ #if SQLITE_MAX_ATTACHED>30 - typedef sqlite3_uint64 tAttachMask; + typedef sqlite3_uint64 yDbMask; #else - typedef unsigned int tAttachMask; + typedef unsigned int yDbMask; #endif /* @@ -2180,8 +2182,8 @@ struct Parse { int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ - tAttachMask writeMask; /* Start a write transaction on these databases */ - tAttachMask cookieMask; /* Bitmask of schema verified databases */ + yDbMask writeMask; /* Start a write transaction on these databases */ + yDbMask cookieMask; /* Bitmask of schema verified databases */ u8 isMultiWrite; /* True if statement may affect/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 65cda0bcc5..5b361b5055 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -302,7 +302,7 @@ struct Vdbe { u8 readOnly; /* True for read-only statements */ u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ - tAttachMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ + yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */ BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7cab12f78d..16d234dd08 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -951,8 +951,8 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ ** in order (and released in reverse order) to avoid deadlocks. */ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - tAttachMask mask; - assert( i>=0 && idb->nDb && i=0 && idb->nDb && ibtreeMask)*8 ); mask = ((u32)1)<btreeMask & mask)==0 ){ From 4fa7d7c0df4a2815abb0fb613786a1dd7173269d Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Apr 2011 02:41:00 +0000 Subject: [PATCH 26/31] Fix typos in comments. No changes to code. FossilOrigin-Name: 28c5f12e98655d5c6167b13e8a15085eca43dd5b --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btmutex.c | 2 +- src/btree.c | 2 +- src/btreeInt.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 927bd9ef71..13d580b533 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\s"tAttachMask"\sdatatype\sto\s"yDbMask". -D 2011-04-02T20:01:02.621 +C Fix\stypos\sin\scomments.\s\sNo\schanges\sto\scode. +D 2011-04-03T02:41:00.238 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,10 +120,10 @@ F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef -F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff -F src/btree.c 2b9c81ff64da339a67dda4f94c0d763627be0b67 +F src/btmutex.c 5ba4ca0216bd9406eccbf50aaf35fef6912c4e2c +F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 -F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4 +F src/btreeInt.h 29ab8a4172f12b04fac34c5a0b76d0df750ddc34 F src/build.c 3a8c6c4b1e16798755d46e699b7fcc12b9f27b2b F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3b91eaaa0b3c25022332ba3d1a5651848fc5d84c -R e5d6d2ab5437a135179f043b3faf09c4 +P 3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa +R 1103ef46d2beca5f9008b7e7268f91fc U drh -Z cdbe2872c525d3ae3a361db4be775f20 +Z 2ee794956e08f440e3a2557effd86b8a diff --git a/manifest.uuid b/manifest.uuid index 6c4bffcf25..eb10573089 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa \ No newline at end of file +28c5f12e98655d5c6167b13e8a15085eca43dd5b \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index 201291a3e9..d772f4b50f 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -195,7 +195,7 @@ void sqlite3BtreeEnterAll(sqlite3 *db){ if( !p->locked ){ assert( p->wantToLock==1 ); while( p->pPrev ) p = p->pPrev; - /* Reason for ALWAYS: There must be at least on unlocked Btree in + /* Reason for ALWAYS: There must be at least one unlocked Btree in ** the chain. Otherwise the !p->locked test above would have failed */ while( p->locked && ALWAYS(p->pNext) ) p = p->pNext; for(pLater = p->pNext; pLater; pLater=pLater->pNext){ diff --git a/src/btree.c b/src/btree.c index 088c555fc6..d86b9edad1 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7990,7 +7990,7 @@ int sqlite3BtreeIsInBackup(Btree *p){ ** ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the -** blob of allocated memory. This function should not call sqlite3_free() +** blob of allocated memory. The xFree function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ diff --git a/src/btreeInt.h b/src/btreeInt.h index 0e71195b0a..a645f4fb97 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -336,7 +336,7 @@ struct BtLock { ** All fields in this structure are accessed under sqlite3.mutex. ** The pBt pointer itself may not be changed while there exists cursors ** in the referenced BtShared that point back to this Btree since those -** cursors have to do go through this Btree to find their BtShared and +** cursors have to go through this Btree to find their BtShared and ** they often do so without holding sqlite3.mutex. */ struct Btree { From dddd779b2bfc818bd2e5f46f01fafbcd89cc7955 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Apr 2011 18:19:25 +0000 Subject: [PATCH 27/31] Make sure that the constant 1 is cast to yDbType before shifting to create an attached database mask. This check-in is a follow-up and fix to the [7aaf8772274422] change that increases the maximum number of attached databases from 30 to 62. FossilOrigin-Name: e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 24 ++++++++++++------------ src/vdbeaux.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 13d580b533..7659f6e29a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypos\sin\scomments.\s\sNo\schanges\sto\scode. -D 2011-04-03T02:41:00.238 +C Make\ssure\sthat\sthe\sconstant\s1\sis\scast\sto\syDbType\sbefore\sshifting\sto\screate\nan\sattached\sdatabase\smask.\s\sThis\scheck-in\sis\sa\sfollow-up\sand\sfix\sto\sthe\n[7aaf8772274422]\schange\sthat\sincreases\sthe\smaximum\snumber\sof\sattached\sdatabases\nfrom\s30\sto\s62. +D 2011-04-03T18:19:25.822 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -235,11 +235,11 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c a45a6a0daf2161797d50b3b5b8a3e0e4debf2d2b +F src/vdbe.c d975adcef86051b6b51c5d2394dd2288e0b0ca81 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 8ee9302ecc1036509956df8aceea6b0b5e0e231c F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 80ed78c8e1edf8918e0e404891d314aa01ccb095 +F src/vdbeaux.c ad921cf58e8c20e1c0a9ef0b7e0f557eabdc7d07 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa -R 1103ef46d2beca5f9008b7e7268f91fc +P 28c5f12e98655d5c6167b13e8a15085eca43dd5b +R 62a2deace5cc72cdc4511f7f5b5d9fa5 U drh -Z 2ee794956e08f440e3a2557effd86b8a +Z 905bef73ef8c243b27a93f7a5f38565e diff --git a/manifest.uuid b/manifest.uuid index eb10573089..b383b69990 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28c5f12e98655d5c6167b13e8a15085eca43dd5b \ No newline at end of file +e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index ddf507ee9d..e6118a4cb5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2789,7 +2789,7 @@ case OP_Transaction: { Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ @@ -2845,7 +2845,7 @@ case OP_ReadCookie: { /* out2-prerelease */ assert( pOp->p3=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb].pBt, iCookie, (u32 *)&iMeta); pOut->u.i = iMeta; @@ -2866,7 +2866,7 @@ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); pIn3 = &aMem[pOp->p3]; @@ -2914,7 +2914,7 @@ case OP_VerifyCookie: { Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); @@ -3018,7 +3018,7 @@ case OP_OpenWrite: { p2 = pOp->p2; iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); @@ -4513,7 +4513,7 @@ case OP_Destroy: { /* out2-prerelease */ }else{ iDb = pOp->p3; assert( iCnt==1 ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; @@ -4549,7 +4549,7 @@ case OP_Clear: { int nChange; nChange = 0; - assert( (p->btreeMask & (1<p2))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); @@ -4594,7 +4594,7 @@ case OP_CreateTable: { /* out2-prerelease */ pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ @@ -4766,7 +4766,7 @@ case OP_IntegrityCk: { } aRoot[j] = 0; assert( pOp->p5nDb ); - assert( (p->btreeMask & (1<p5))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, (int)pnErr->u.i, &nErr); sqlite3DbFree(db, aRoot); @@ -5303,7 +5303,7 @@ case OP_JournalMode: { /* out2-prerelease */ ** No other mutexes are required by the ATTACH command so this is safe ** to do. */ - assert( (p->btreeMask & (1<p1))!=0 || p->aMutex.nMutex==0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 || p->aMutex.nMutex==0 ); if( p->aMutex.nMutex==0 ){ /* This occurs right after ATTACH. Get a mutex on the newly ATTACHed ** database. */ @@ -5408,7 +5408,7 @@ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ @@ -5457,7 +5457,7 @@ case OP_TableLock: { if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ int p1 = pOp->p1; assert( p1>=0 && p1nDb ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[p1].pBt, pOp->p2, isWriteLock); if( (rc&0xFF)==SQLITE_LOCKED ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 16d234dd08..de02d021af 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -954,7 +954,7 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ yDbMask mask; assert( i>=0 && idb->nDb && ibtreeMask)*8 ); - mask = ((u32)1)<btreeMask & mask)==0 ){ p->btreeMask |= mask; sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); From bdaec52c6218c59e7f45d9894834843bb2c8aceb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 00:14:43 +0000 Subject: [PATCH 28/31] Remove the BtreeMutexArray object - use the Vdbe.btreeMask field to accomplish the same result. Add a generation counter to btree mutexes in order to assert that mutexes are never temporarily dropped over a range of instructions in order to do deadlock avoidance in some subroutine. Lock all btrees in any Vdbe program that uses OP_ParseSchema. FossilOrigin-Name: d81708f7d1eee399bfe76f6b8dac950a85dc2582 --- manifest | 22 +++---- manifest.uuid | 2 +- src/btmutex.c | 137 ++++++++++++++--------------------------- src/btree.h | 20 +----- src/btreeInt.h | 3 +- src/vdbe.c | 81 +++++++++++++++--------- src/vdbeInt.h | 11 ++-- src/vdbeaux.c | 164 ++++++++++++++++++++++++++++++++++++------------- 8 files changed, 242 insertions(+), 198 deletions(-) diff --git a/manifest b/manifest index 7659f6e29a..54a041dd07 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\sthe\sconstant\s1\sis\scast\sto\syDbType\sbefore\sshifting\sto\screate\nan\sattached\sdatabase\smask.\s\sThis\scheck-in\sis\sa\sfollow-up\sand\sfix\sto\sthe\n[7aaf8772274422]\schange\sthat\sincreases\sthe\smaximum\snumber\sof\sattached\sdatabases\nfrom\s30\sto\s62. -D 2011-04-03T18:19:25.822 +C Remove\sthe\sBtreeMutexArray\sobject\s-\suse\sthe\sVdbe.btreeMask\sfield\sto\saccomplish\nthe\ssame\sresult.\s\sAdd\sa\sgeneration\scounter\sto\sbtree\smutexes\sin\sorder\sto\sassert\nthat\smutexes\sare\snever\stemporarily\sdropped\sover\sa\srange\sof\sinstructions\sin\sorder\nto\sdo\sdeadlock\savoidance\sin\ssome\ssubroutine.\s\sLock\sall\sbtrees\sin\sany\sVdbe\nprogram\sthat\suses\sOP_ParseSchema. +D 2011-04-04T00:14:43.936 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,10 +120,10 @@ F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef -F src/btmutex.c 5ba4ca0216bd9406eccbf50aaf35fef6912c4e2c +F src/btmutex.c 3e595ee1bb99e3a1f16824137b435ffc97c98e5f F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 -F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 -F src/btreeInt.h 29ab8a4172f12b04fac34c5a0b76d0df750ddc34 +F src/btree.h a840a20c1969391f98ee06960d5ee2dc460186b3 +F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991 F src/build.c 3a8c6c4b1e16798755d46e699b7fcc12b9f27b2b F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -235,11 +235,11 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c d975adcef86051b6b51c5d2394dd2288e0b0ca81 +F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h 8ee9302ecc1036509956df8aceea6b0b5e0e231c +F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c ad921cf58e8c20e1c0a9ef0b7e0f557eabdc7d07 +F src/vdbeaux.c 1a98cc953a316739c3e9a2930ae0eee517d37def F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 28c5f12e98655d5c6167b13e8a15085eca43dd5b -R 62a2deace5cc72cdc4511f7f5b5d9fa5 +P e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 +R 5eec5b6c06a45dcfcec6cc2765ee2ab8 U drh -Z 905bef73ef8c243b27a93f7a5f38565e +Z 9f8e37bd1010a379addad04d1c835970 diff --git a/manifest.uuid b/manifest.uuid index b383b69990..34a2869ab5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 \ No newline at end of file +d81708f7d1eee399bfe76f6b8dac950a85dc2582 \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index d772f4b50f..42d0bdcbc7 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -39,15 +39,34 @@ static void lockBtreeMutex(Btree *p){ ** clear the p->locked boolean. */ static void unlockBtreeMutex(Btree *p){ + BtShared *pBt = p->pBt; assert( p->locked==1 ); - assert( sqlite3_mutex_held(p->pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3_mutex_held(p->db->mutex) ); - assert( p->db==p->pBt->db ); + assert( p->db==pBt->db ); - sqlite3_mutex_leave(p->pBt->mutex); + pBt->iMutexCounter++; + sqlite3_mutex_leave(pBt->mutex); p->locked = 0; } +#ifdef SQLITE_DEBUG +/* +** Return the number of times that the mutex has been exited for +** the given btree. +** +** This is a small circular counter that wraps around to zero on +** overflow. It is used only for sanity checking - to verify that +** mutexes are held continously by asserting that the value of +** this counter at the beginning of a region is the same as at +** the end. +*/ +u32 sqlite3BtreeMutexCounter(Btree *p){ + assert( p->locked==1 || p->sharable==0 ); + return p->pBt->iMutexCounter; +} +#endif + /* ** Enter a mutex on the given BTree object. ** @@ -92,6 +111,24 @@ void sqlite3BtreeEnter(Btree *p){ p->wantToLock++; if( p->locked ) return; + /* Increment the mutex counter on all locked btrees in the same + ** database connection. This simulates the unlocking that would + ** occur on a worst-case mutex dead-lock avoidance scenario. + */ +#ifdef SQLITE_DEBUG + { + int ii; + sqlite3 *db = p->db; + Btree *pOther; + for(ii=0; iinDb; ii++){ + if( ii==1 ) continue; + pOther = db->aDb[ii].pBt; + if( pOther==0 || pOther->sharable==0 || pOther->locked==0 ) continue; + pOther->pBt->iMutexCounter++; + } + } +#endif + /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock ** procedure that follows. Just be sure not to block. @@ -251,97 +288,17 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ } #endif /* NDEBUG */ +#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ /* -** Add a new Btree pointer to a BtreeMutexArray. -** if the pointer can possibly be shared with -** another database connection. +** The following are special cases for mutex enter routines for use +** in single threaded applications that use shared cache. Except for +** these two routines, all mutex operations are no-ops in that case and +** are null #defines in btree.h. ** -** The pointers are kept in sorted order by pBtree->pBt. That -** way when we go to enter all the mutexes, we can enter them -** in order without every having to backup and retry and without -** worrying about deadlock. -** -** The number of shared btrees will always be small (usually 0 or 1) -** so an insertion sort is an adequate algorithm here. +** If shared cache is disabled, then all btree mutex routines, including +** the ones below, are no-ops and are null #defines in btree.h. */ -void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ - int i, j; - BtShared *pBt; - if( pBtree==0 || pBtree->sharable==0 ) return; -#ifndef NDEBUG - { - for(i=0; inMutex; i++){ - assert( pArray->aBtree[i]!=pBtree ); - } - } -#endif - assert( pArray->nMutex>=0 ); - assert( pArray->nMutexaBtree)-1 ); - pBt = pBtree->pBt; - for(i=0; inMutex; i++){ - assert( pArray->aBtree[i]!=pBtree ); - if( pArray->aBtree[i]->pBt>pBt ){ - for(j=pArray->nMutex; j>i; j--){ - pArray->aBtree[j] = pArray->aBtree[j-1]; - } - pArray->aBtree[i] = pBtree; - pArray->nMutex++; - return; - } - } - pArray->aBtree[pArray->nMutex++] = pBtree; -} -/* -** Enter the mutex of every btree in the array. This routine is -** called at the beginning of sqlite3VdbeExec(). The mutexes are -** exited at the end of the same function. -*/ -void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){ - int i; - for(i=0; inMutex; i++){ - Btree *p = pArray->aBtree[i]; - /* Some basic sanity checking */ - assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); - assert( !p->locked || p->wantToLock>0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - /* The Btree is sharable because only sharable Btrees are entered - ** into the array in the first place. */ - assert( p->sharable ); - - p->wantToLock++; - if( !p->locked ){ - lockBtreeMutex(p); - } - } -} - -/* -** Leave the mutex of every btree in the group. -*/ -void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ - int i; - for(i=0; inMutex; i++){ - Btree *p = pArray->aBtree[i]; - /* Some basic sanity checking */ - assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); - assert( p->locked ); - assert( p->wantToLock>0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - p->wantToLock--; - if( p->wantToLock==0 ){ - unlockBtreeMutex(p); - } - } -} - -#else void sqlite3BtreeEnter(Btree *p){ p->pBt->db = p->db; } diff --git a/src/btree.h b/src/btree.h index 468723b33e..4fd4f67685 100644 --- a/src/btree.h +++ b/src/btree.h @@ -39,18 +39,6 @@ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; -typedef struct BtreeMutexArray BtreeMutexArray; - -/* -** This structure records all of the Btrees that need to hold -** a mutex before we enter sqlite3VdbeExec(). The Btrees are -** are placed in aBtree[] in order of aBtree[]->pBt. That way, -** we can always lock and unlock them all quickly. -*/ -struct BtreeMutexArray { - int nMutex; - Btree *aBtree[SQLITE_MAX_ATTACHED+1]; -}; int sqlite3BtreeOpen( @@ -228,23 +216,19 @@ void sqlite3BtreeCursorList(Btree*); void sqlite3BtreeEnterCursor(BtCursor*); void sqlite3BtreeLeaveCursor(BtCursor*); void sqlite3BtreeLeaveAll(sqlite3*); - void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); - void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); - void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); #ifndef NDEBUG /* These routines are used inside assert() statements only. */ int sqlite3BtreeHoldsMutex(Btree*); int sqlite3BtreeHoldsAllMutexes(sqlite3*); + u32 sqlite3BtreeMutexCounter(Btree*); #endif #else # define sqlite3BtreeLeave(X) +# define sqlite3BtreeMutexCounter(X) 0 # define sqlite3BtreeEnterCursor(X) # define sqlite3BtreeLeaveCursor(X) # define sqlite3BtreeLeaveAll(X) -# define sqlite3BtreeMutexArrayEnter(X) -# define sqlite3BtreeMutexArrayLeave(X) -# define sqlite3BtreeMutexArrayInsert(X,Y) # define sqlite3BtreeHoldsMutex(X) 1 # define sqlite3BtreeHoldsAllMutexes(X) 1 diff --git a/src/btreeInt.h b/src/btreeInt.h index a645f4fb97..2aee063d39 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -426,7 +426,7 @@ struct BtShared { u32 nPage; /* Number of pages in the database */ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ - sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ + sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */ Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ #ifndef SQLITE_OMIT_SHARED_CACHE int nRef; /* Number of references to this structure */ @@ -435,6 +435,7 @@ struct BtShared { Btree *pWriter; /* Btree with currently open write transaction */ u8 isExclusive; /* True if pWriter has an EXCLUSIVE lock on the db */ u8 isPending; /* If waiting for read-locks to clear */ + u16 iMutexCounter; /* The number of mutex_leave(mutex) calls */ #endif u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ }; diff --git a/src/vdbe.c b/src/vdbe.c index e6118a4cb5..eff4d86cf9 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -571,7 +571,7 @@ int sqlite3VdbeExec( /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ @@ -1394,6 +1394,7 @@ case OP_Function: { ctx.pColl = pOp[-1].p4.pColl; } (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + sqlite3VdbeMutexResync(p); if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function @@ -1404,6 +1405,17 @@ case OP_Function: { goto no_mem; } + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ +#if 0 + if( p->expired ){ + rc = SQLITE_ABORT; + break; + } +#endif + /* If any auxiliary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ @@ -2650,6 +2662,7 @@ case OP_Savepoint: { if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetInternalSchema(db, 0); + sqlite3VdbeMutexResync(p); db->flags = (db->flags | SQLITE_InternChanges); } } @@ -2940,6 +2953,7 @@ case OP_VerifyCookie: { */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ sqlite3ResetInternalSchema(db, pOp->p1); + sqlite3VdbeMutexResync(p); } p->expired = 1; @@ -4622,29 +4636,22 @@ case OP_ParseSchema: { char *zSql; InitData initData; + /* Any prepared statement that invokes this opcode will hold mutexes + ** on every btree. This is a prerequisite for invoking + ** sqlite3InitCallback(). + */ +#ifdef SQLITE_DEBUG + for(iDb=0; iDbnDb; iDb++){ + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + } +#endif + assert( p->btreeMask == ~(yDbMask)0 ); + + iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); - - /* When this opcode is invoked, it is guaranteed that the b-tree mutex - ** is held and the schema is loaded for database iDb. However, at the - ** start of the sqlite3_exec() call below, SQLite will invoke - ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the iDb - ** mutex may be temporarily released to avoid deadlock. If this happens, - ** then some other thread may delete the in-memory schema of database iDb - ** before the SQL statement runs. The schema will not be reloaded because - ** the db->init.busy flag is set. This can result in a "no such table: - ** sqlite_master" or "malformed database schema" error being returned to - ** the user. - ** - ** To avoid this, obtain all mutexes and check that no other thread has - ** deleted the schema before calling sqlite3_exec(). If we find that the - ** another thread has deleted the schema, there is no need to update it. - ** The updated schema will be loaded from disk when it is next required. - */ - assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); - sqlite3BtreeEnterAll(db); - if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){ + /* Used to be a conditional */ { zMaster = SCHEMA_TABLE(iDb); initData.db = db; initData.iDb = pOp->p1; @@ -4665,7 +4672,6 @@ case OP_ParseSchema: { db->init.busy = 0; } } - sqlite3BtreeLeaveAll(db); if( rc==SQLITE_NOMEM ){ goto no_mem; } @@ -5190,11 +5196,25 @@ case OP_AggStep: { ctx.pColl = pOp[-1].p4.pColl; } (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + sqlite3VdbeMutexResync(p); if( ctx.isError ){ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); rc = ctx.isError; } + + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ +#if 0 + if( p->expired ){ + rc = SQLITE_ABORT; + break; + } +#endif + sqlite3VdbeMemRelease(&ctx.s); + break; } @@ -5216,8 +5236,11 @@ case OP_AggFinal: { pMem = &aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); + sqlite3VdbeMutexResync(p); if( rc ){ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); + }else if( p->expired ){ + rc = SQLITE_ABORT; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); @@ -5294,7 +5317,7 @@ case OP_JournalMode: { /* out2-prerelease */ /* This opcode is used in two places: PRAGMA journal_mode and ATTACH. ** In PRAGMA journal_mode, the sqlite3VdbeUsesBtree() routine is called - ** when the statment is prepared and so p->aMutex.nMutex>0. All mutexes + ** when the statement is prepared and so p->btreeMask!=0. All mutexes ** are already acquired. But when used in ATTACH, sqlite3VdbeUsesBtree() ** is not called when the statement is prepared because it requires the ** iDb index of the database as a parameter, and the database has not @@ -5303,12 +5326,11 @@ case OP_JournalMode: { /* out2-prerelease */ ** No other mutexes are required by the ATTACH command so this is safe ** to do. */ - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 || p->aMutex.nMutex==0 ); - if( p->aMutex.nMutex==0 ){ + if( p->btreeMask==0 ){ /* This occurs right after ATTACH. Get a mutex on the newly ATTACHed ** database. */ sqlite3VdbeUsesBtree(p, pOp->p1); - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); } pBt = db->aDb[pOp->p1].pBt; @@ -5946,13 +5968,16 @@ vdbe_error_halt: sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; - if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); + if( resetSchemaOnFault ){ + sqlite3ResetInternalSchema(db, 0); + sqlite3VdbeMutexResync(p); + } /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 5b361b5055..15e4a812a7 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -303,9 +303,9 @@ struct Vdbe { u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ + u32 iMutexCounter; /* Mutex counter upon sqlite3VdbeEnter() */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */ - BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif @@ -387,6 +387,9 @@ int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); void sqlite3VdbeMemStoreType(Mem *pMem); +void sqlite3VdbeEnter(Vdbe*); +void sqlite3VdbeLeave(Vdbe*); +void sqlite3VdbeMutexResync(Vdbe*); #ifdef SQLITE_DEBUG void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); @@ -398,12 +401,6 @@ int sqlite3VdbeCheckFk(Vdbe *, int); # define sqlite3VdbeCheckFk(p,i) 0 #endif -#ifndef SQLITE_OMIT_SHARED_CACHE -void sqlite3VdbeMutexArrayEnter(Vdbe *p); -#else -# define sqlite3VdbeMutexArrayEnter(p) -#endif - int sqlite3VdbeMemTranslate(Mem*, u8); #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index de02d021af..6710b32ab0 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -157,6 +157,11 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; p->expired = 0; + if( op==OP_ParseSchema ){ + /* Any program that uses the OP_ParseSchema opcode needs to lock + ** all btrees. */ + p->btreeMask = ~(yDbMask)0; + } #ifdef SQLITE_DEBUG pOp->zComment = 0; if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); @@ -457,7 +462,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ assert( aOp && !p->db->mallocFailed ); /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ - assert( p->aMutex.nMutex==0 ); + assert( p->btreeMask==0 ); resolveP2Values(p, pnMaxArg); *pnOp = p->nOp; @@ -945,22 +950,123 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** -** The prepared statement has to know in advance which Btree objects -** will be used so that it can acquire mutexes on them all in sorted -** order (via sqlite3VdbeMutexArrayEnter(). Mutexes are acquired -** in order (and released in reverse order) to avoid deadlocks. +** The prepared statements need to know in advance the complete set of +** attached databases that they will be using. A mask of these databases +** is maintained in p->btreeMask and is used for locking and other purposes. */ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - yDbMask mask; assert( i>=0 && idb->nDb && ibtreeMask)*8 ); - mask = ((yDbMask)1)<btreeMask & mask)==0 ){ - p->btreeMask |= mask; - sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); - } + p->btreeMask |= ((yDbMask)1)<db; + Db *aDb = db->aDb; + int nDb = db->nDb; + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + cntSum += sqlite3BtreeMutexCounter(aDb[i].pBt); + } + } +#endif + return cntSum; +} +#endif + +/* +** If SQLite is compiled to support shared-cache mode and to be threadsafe, +** this routine obtains the mutex associated with each BtShared structure +** that may be accessed by the VM passed as an argument. In doing so it also +** sets the BtShared.db member of each of the BtShared structures, ensuring +** that the correct busy-handler callback is invoked if required. +** +** If SQLite is not threadsafe but does support shared-cache mode, then +** sqlite3BtreeEnter() is invoked to set the BtShared.db variables +** of all of BtShared structures accessible via the database handle +** associated with the VM. +** +** If SQLite is not threadsafe and does not support shared-cache mode, this +** function is a no-op. +** +** The p->btreeMask field is a bitmask of all btrees that the prepared +** statement p will ever use. Let N be the number of bits in p->btreeMask +** corresponding to btrees that use shared cache. Then the runtime of +** this routine is N*N. But as N is rarely more than 1, this should not +** be a problem. +*/ +void sqlite3VdbeEnter(Vdbe *p){ +#ifndef SQLITE_OMIT_SHARED_CACHE + int i; + yDbMask mask; + sqlite3 *db = p->db; + Db *aDb = db->aDb; + int nDb = db->nDb; + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeEnter(aDb[i].pBt); + } + } + p->iMutexCounter = mutexCounterSum(p); +#endif +} + +/* +** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). +*/ +void sqlite3VdbeLeave(Vdbe *p){ +#ifndef SQLITE_OMIT_SHARED_CACHE + int i; + yDbMask mask; + sqlite3 *db = p->db; + Db *aDb = db->aDb; + int nDb = db->nDb; + + /* Assert that the all mutexes have been held continously since + ** the most recent sqlite3VdbeEnter() or sqlite3VdbeMutexResync(). + */ + assert( mutexCounterSum(p) == p->iMutexCounter ); + + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeLeave(aDb[i].pBt); + } + } +#endif +} + +/* +** Recompute the sum of the mutex counters on all btrees used by the +** prepared statement p. +** +** Call this routine while holding a sqlite3VdbeEnter() after doing something +** that might cause one or more of the individual mutexes held by the +** prepared statement to be released. Calling sqlite3BtreeEnter() on +** any BtShared mutex which is not used by the prepared statement is one +** way to cause one or more of the mutexes in the prepared statement +** to be temporarily released. The anti-deadlocking logic in +** sqlite3BtreeEnter() can cause mutexes to be released temporarily then +** reacquired. +** +** Calling this routine is an acknowledgement that some of the individual +** mutexes in the prepared statement might have been released and reacquired. +** So checks to verify that mutex-protected content did not change +** unexpectedly should accompany any call to this routine. +*/ +void sqlite3VdbeMutexResync(Vdbe *p){ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && defined(SQLITE_DEBUG) + p->iMutexCounter = mutexCounterSum(p); +#endif +} #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* @@ -1959,33 +2065,6 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ return rc; } -/* -** If SQLite is compiled to support shared-cache mode and to be threadsafe, -** this routine obtains the mutex associated with each BtShared structure -** that may be accessed by the VM passed as an argument. In doing so it -** sets the BtShared.db member of each of the BtShared structures, ensuring -** that the correct busy-handler callback is invoked if required. -** -** If SQLite is not threadsafe but does support shared-cache mode, then -** sqlite3BtreeEnterAll() is invoked to set the BtShared.db variables -** of all of BtShared structures accessible via the database handle -** associated with the VM. Of course only a subset of these structures -** will be accessed by the VM, and we could use Vdbe.btreeMask to figure -** that subset out, but there is no advantage to doing so. -** -** If SQLite is not threadsafe and does not support shared-cache mode, this -** function is a no-op. -*/ -#ifndef SQLITE_OMIT_SHARED_CACHE -void sqlite3VdbeMutexArrayEnter(Vdbe *p){ -#if SQLITE_THREADSAFE - sqlite3BtreeMutexArrayEnter(&p->aMutex); -#else - sqlite3BtreeEnterAll(p->db); -#endif -} -#endif - /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be @@ -2058,7 +2137,7 @@ int sqlite3VdbeHalt(Vdbe *p){ int isSpecialError; /* Set to true if a 'special' error */ /* Lock all btrees used by the statement */ - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); /* Check for one of the special errors */ mrc = p->rc & 0xff; @@ -2112,7 +2191,7 @@ int sqlite3VdbeHalt(Vdbe *p){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return SQLITE_ERROR; } rc = SQLITE_CONSTRAINT; @@ -2124,7 +2203,7 @@ int sqlite3VdbeHalt(Vdbe *p){ rc = vdbeCommit(db, p); } if( rc==SQLITE_BUSY && p->readOnly ){ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; @@ -2196,7 +2275,8 @@ int sqlite3VdbeHalt(Vdbe *p){ } /* Release the locks */ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeMutexResync(p); + sqlite3VdbeLeave(p); } /* We have successfully halted and closed the VM. Record this fact. */ From dfdc48e157103b6ba04a28c5a0bf08b84090cb1a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 03:27:16 +0000 Subject: [PATCH 29/31] Suppress unused parameter warnings in sqlite3VdbeEnter() and related routines. FossilOrigin-Name: f8e98ab3062a6e56924a86e8f3204c30d0f3d906 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 54a041dd07..0f239ebce6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sBtreeMutexArray\sobject\s-\suse\sthe\sVdbe.btreeMask\sfield\sto\saccomplish\nthe\ssame\sresult.\s\sAdd\sa\sgeneration\scounter\sto\sbtree\smutexes\sin\sorder\sto\sassert\nthat\smutexes\sare\snever\stemporarily\sdropped\sover\sa\srange\sof\sinstructions\sin\sorder\nto\sdo\sdeadlock\savoidance\sin\ssome\ssubroutine.\s\sLock\sall\sbtrees\sin\sany\sVdbe\nprogram\sthat\suses\sOP_ParseSchema. -D 2011-04-04T00:14:43.936 +C Suppress\sunused\sparameter\swarnings\sin\ssqlite3VdbeEnter()\sand\srelated\sroutines. +D 2011-04-04T03:27:16.245 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -239,7 +239,7 @@ F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 1a98cc953a316739c3e9a2930ae0eee517d37def +F src/vdbeaux.c 010e4e67a5a577451b0220ea8903c9e279a43248 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 -R 5eec5b6c06a45dcfcec6cc2765ee2ab8 +P d81708f7d1eee399bfe76f6b8dac950a85dc2582 +R a4fe05a3c45b7dfebc2c0e1b1ce8761a U drh -Z 9f8e37bd1010a379addad04d1c835970 +Z 802ab81287251956931cb7c1ec2989a0 diff --git a/manifest.uuid b/manifest.uuid index 34a2869ab5..dc9d29b53a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d81708f7d1eee399bfe76f6b8dac950a85dc2582 \ No newline at end of file +f8e98ab3062a6e56924a86e8f3204c30d0f3d906 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 6710b32ab0..b28bac4f36 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -978,6 +978,8 @@ static u32 mutexCounterSum(Vdbe *p){ cntSum += sqlite3BtreeMutexCounter(aDb[i].pBt); } } +#else + UNUSED_PARAMETER(p); #endif return cntSum; } @@ -1017,6 +1019,8 @@ void sqlite3VdbeEnter(Vdbe *p){ } } p->iMutexCounter = mutexCounterSum(p); +#else + UNUSED_PARAMETER(p); #endif } @@ -1041,6 +1045,8 @@ void sqlite3VdbeLeave(Vdbe *p){ sqlite3BtreeLeave(aDb[i].pBt); } } +#else + UNUSED_PARAMETER(p); #endif } @@ -1065,6 +1071,8 @@ void sqlite3VdbeLeave(Vdbe *p){ void sqlite3VdbeMutexResync(Vdbe *p){ #if !defined(SQLITE_OMIT_SHARED_CACHE) && defined(SQLITE_DEBUG) p->iMutexCounter = mutexCounterSum(p); +#else + UNUSED_PARAMETER(p); #endif } From 26ec621a9f60b69224122df4010c0e774bb75623 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 4 Apr 2011 07:05:38 +0000 Subject: [PATCH 30/31] Changes to oserror.test and syscall.test so that they work with the in-memory journal permutation test. FossilOrigin-Name: 4e996f36c73c5e768a954394fcbbf5e17576c807 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/oserror.test | 12 ++++++++---- test/syscall.test | 6 ++++-- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 0f239ebce6..66bd679080 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Suppress\sunused\sparameter\swarnings\sin\ssqlite3VdbeEnter()\sand\srelated\sroutines. -D 2011-04-04T03:27:16.245 +C Changes\sto\soserror.test\sand\ssyscall.test\sso\sthat\sthey\swork\swith\sthe\sin-memory\sjournal\spermutation\stest. +D 2011-04-04T07:05:38.773 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -594,7 +594,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/oserror.test 0abf1b4a935aae329b95da27388d7ca61aaea6f0 +F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f @@ -677,7 +677,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 -F test/syscall.test b967e1f5405bb1c9e2e223dbf7d7cd35220589a3 +F test/syscall.test 02e5359bf4f5e6f716696318fde4e0b5c2c70d21 F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d81708f7d1eee399bfe76f6b8dac950a85dc2582 -R a4fe05a3c45b7dfebc2c0e1b1ce8761a -U drh -Z 802ab81287251956931cb7c1ec2989a0 +P f8e98ab3062a6e56924a86e8f3204c30d0f3d906 +R f1bbd3f7ef415e82a6c1a2591a207c23 +U dan +Z 67d15952b786647f2d72d97293a23816 diff --git a/manifest.uuid b/manifest.uuid index dc9d29b53a..62255888e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f8e98ab3062a6e56924a86e8f3204c30d0f3d906 \ No newline at end of file +4e996f36c73c5e768a954394fcbbf5e17576c807 \ No newline at end of file diff --git a/test/oserror.test b/test/oserror.test index 82a5d5f6ff..2d3a24a8f5 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -100,13 +100,17 @@ do_test 2.1.1 { set ::log [list] file mkdir test.db-wal forcedelete test.db - sqlite3 dbh test.db - catchsql { SELECT * FROM sqlite_master } dbh + list [catch { + sqlite3 dbh test.db + execsql { SELECT * FROM sqlite_master } dbh + } msg] $msg } {1 {disk I/O error}} -do_re_test 2.1.2 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - } +do_re_test 2.1.2 { + lindex $::log 0 +} {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - } do_test 2.1.3 { - dbh close + catch { dbh close } forcedelete test.db-wal } {} diff --git a/test/syscall.test b/test/syscall.test index 95921bd35e..6aca75ec39 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -221,8 +221,10 @@ foreach {nByte res} { } { do_test 7.$nByte { create_db_file $nByte - sqlite3 db test.db - catchsql { CREATE TABLE t1(a, b) } + list [catch { + sqlite3 db test.db + execsql { CREATE TABLE t1(a, b) } + } msg] $msg } $res catch { db close } } From 7b94e7f8382b0a29b12e3ee2427331d41a6a0061 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 12:29:20 +0000 Subject: [PATCH 31/31] Move the expired-statement test for OP_Function until after all memory has been freed. The test is still commented out, however. FossilOrigin-Name: 425e3edb146c497817855dd741878709a25c8b98 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 20 +++++++++----------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 66bd679080..65800fd981 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\soserror.test\sand\ssyscall.test\sso\sthat\sthey\swork\swith\sthe\sin-memory\sjournal\spermutation\stest. -D 2011-04-04T07:05:38.773 +C Move\sthe\sexpired-statement\stest\sfor\sOP_Function\suntil\safter\sall\smemory\shas\nbeen\sfreed.\s\sThe\stest\sis\sstill\scommented\sout,\showever. +D 2011-04-04T12:29:20.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -235,7 +235,7 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f +F src/vdbe.c 6488f759929602cbc3acea5e9c7c10e2d2cd00ed F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f8e98ab3062a6e56924a86e8f3204c30d0f3d906 -R f1bbd3f7ef415e82a6c1a2591a207c23 -U dan -Z 67d15952b786647f2d72d97293a23816 +P 4e996f36c73c5e768a954394fcbbf5e17576c807 +R 4c64876ffe2c0a670add1f1b62152ed8 +U drh +Z badc0ef9dd3fcc800ebaf4f50ec0d36c diff --git a/manifest.uuid b/manifest.uuid index 62255888e6..3a4413c91a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e996f36c73c5e768a954394fcbbf5e17576c807 \ No newline at end of file +425e3edb146c497817855dd741878709a25c8b98 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index eff4d86cf9..4bfe518a9c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1405,17 +1405,6 @@ case OP_Function: { goto no_mem; } - /* The app-defined function has done something that as caused this - ** statement to expire. (Perhaps the function called sqlite3_exec() - ** with a CREATE TABLE statement.) - */ -#if 0 - if( p->expired ){ - rc = SQLITE_ABORT; - break; - } -#endif - /* If any auxiliary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ @@ -1437,6 +1426,15 @@ case OP_Function: { if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } + +#if 0 + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ + if( p->expired ) rc = SQLITE_ABORT; +#endif + REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); break;