diff --git a/manifest b/manifest index 1b7bb9a180..296d435e22 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sos_unix.c\sso\sthat,\sunless\s8.3\sfilenames\sare\sactually\sin\suse,\sjournal\sand\swal\sfile\spermissions\sare\sassigned\scorrectly\seven\sif\sSQLITE_ENABLE_8_3_NAMES\sis\sdefined. -D 2011-12-12T19:48:43.750 +C Merge\sthe\snx-devkit\schanges\sinto\strunk. +D 2011-12-13T15:37:12.235 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -146,8 +146,8 @@ F src/insert.c ea820fe9af748075b3b6827fb6f23f25079bf1f7 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 -F src/loadext.c d0d2022a5a07274d408820b978b9e549189d314f -F src/main.c e10d5ad24ae1964d1dc53fbc283557c1c5cd29f3 +F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d +F src/main.c b4c74ff20abd393b14b3cf7b2130758e2187a5b2 F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 7998e7003a3047e323c849a26dda004debc04d03 @@ -214,7 +214,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5 -F src/test_multiplex.c 7dcf429b53f5f5ef22bba7987bea61234a0c7418 +F src/test_multiplex.c 10aaf8b7ebeb74f82d5c96e06c398b776917e457 F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec @@ -605,8 +605,9 @@ F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test eafaa41b9133d7a2ded4641bbe5f340731d35a52 F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054 -F test/multiplex.test 770f0295dd6673e60458cb93abd033ed2f253291 +F test/multiplex.test 8bc3c71f73fe833bc8a659d454d320044a33b5da F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a +F test/multiplex3.test cbc0d03da5fcd0c18a33a8973ef1df1b4bc2100a F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a @@ -979,7 +980,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P ee1e012256ae8010b6b6c4895a74b6883f20e73c -R 6f54deb234c6e01cb7083112d4738ce0 -U dan -Z 1fe68808d0e2249c5544c1978ff3d49d +P 169e12295cca701443746b1209bd6a7714fd8988 2eb79efbff9cdab843b172e9fa9fb400c542fab1 +R e5aa0bc552fbb5033b8311d030f5558d +U drh +Z afe5f3537b446035b4ee9315704cbe8b diff --git a/manifest.uuid b/manifest.uuid index a794f24ca6..2ba39b2ac4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -169e12295cca701443746b1209bd6a7714fd8988 \ No newline at end of file +03a70c3dae8d912fccd9d72c575dc372b198d238 \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index e9c97adff3..3fcf5008cf 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -625,6 +625,7 @@ void sqlite3_reset_auto_extension(void){ void sqlite3AutoLoadExtensions(sqlite3 *db){ int i; int go = 1; + int rc; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); wsdAutoextInit; @@ -647,8 +648,8 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){ } sqlite3_mutex_leave(mutex); zErrmsg = 0; - if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){ - sqlite3Error(db, SQLITE_ERROR, + if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ + sqlite3Error(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; } diff --git a/src/main.c b/src/main.c index d6dc0c79ed..f4519c5b36 100644 --- a/src/main.c +++ b/src/main.c @@ -257,6 +257,10 @@ int sqlite3_initialize(void){ */ int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ +#ifdef SQLITE_EXTRA_SHUTDOWN + void SQLITE_EXTRA_SHUTDOWN(void); + SQLITE_EXTRA_SHUTDOWN(); +#endif sqlite3_os_end(); sqlite3_reset_auto_extension(); sqlite3GlobalConfig.isInit = 0; @@ -2239,10 +2243,13 @@ static int openDatabase( /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ - sqlite3AutoLoadExtensions(db); rc = sqlite3_errcode(db); - if( rc!=SQLITE_OK ){ - goto opendb_out; + if( rc==SQLITE_OK ){ + sqlite3AutoLoadExtensions(db); + rc = sqlite3_errcode(db); + if( rc!=SQLITE_OK ){ + goto opendb_out; + } } #ifdef SQLITE_ENABLE_FTS1 diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 091f2395fd..ce55bad083 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -213,71 +213,6 @@ static int multiplexStrlen30(const char *z){ return 0x3fffffff & (int)(z2 - z); } -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at pOrigVfs->mxPathname characters. This function departs -** from the traditional temporary name generation in the os_win -** and os_unix VFS in several ways, but is necessary so that -** the file name is known for temporary files (like those used -** during vacuum.) -** -** N.B. This routine assumes your underlying VFS is ok with using -** "/" as a directory seperator. This is the default for UNIXs -** and is allowed (even mixed) for most versions of Windows. -*/ -static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){ - static char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i,j; - int attempts = 0; - int exists = 0; - int rc = SQLITE_ERROR; - - /* Check that the output buffer is large enough for - ** pVfs->mxPathname characters. - */ - if( pOrigVfs->mxPathname <= nBuf ){ - char *zTmp = sqlite3_malloc(pOrigVfs->mxPathname); - if( zTmp==0 ) return SQLITE_NOMEM; - - /* sqlite3_temp_directory should always be less than - ** pVfs->mxPathname characters. - */ - sqlite3_snprintf(pOrigVfs->mxPathname, - zTmp, - "%s/", - sqlite3_temp_directory ? sqlite3_temp_directory : "."); - rc = pOrigVfs->xFullPathname(pOrigVfs, zTmp, nBuf, zBuf); - sqlite3_free(zTmp); - if( rc ) return rc; - - /* Check that the output buffer is large enough for the temporary file - ** name. - */ - j = multiplexStrlen30(zBuf); - if( (j + 8 + 1 + 3 + 1) <= nBuf ){ - /* Make 3 attempts to generate a unique name. */ - do { - attempts++; - sqlite3_randomness(8, &zBuf[j]); - for(i=0; i<8; i++){ - unsigned char uc = (unsigned char)zBuf[j+i]; - zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)]; - } - memcpy(&zBuf[j+i], ".tmp", 5); - rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists); - } while ( (rc==SQLITE_OK) && exists && (attempts<3) ); - if( rc==SQLITE_OK && exists ){ - rc = SQLITE_ERROR; - } - } - } - - return rc; -} - /* Compute the filename for the iChunk-th chunk */ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ @@ -291,7 +226,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ pGroup->aReal = p; pGroup->nReal = iChunk+1; } - if( pGroup->aReal[iChunk].z==0 ){ + if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){ char *z; int n = pGroup->nName; pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 ); @@ -461,6 +396,7 @@ static int multiplexOpen( UNUSED_PARAMETER(pVfs); memset(pConn, 0, pVfs->szOsFile); + assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) ); /* We need to create a group structure and manage ** access to this group of files. @@ -468,23 +404,9 @@ static int multiplexOpen( multiplexEnter(); pMultiplexOpen = (multiplexConn*)pConn; - /* If the second argument to this function is NULL, generate a - ** temporary file name to use. This will be handled by the - ** original xOpen method. We just need to allocate space for - ** it. - */ - if( !zName ){ - zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 ); - if( zName==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree); - } - } - if( rc==SQLITE_OK ){ /* allocate space for group */ - nName = multiplexStrlen30(zName); + nName = zName ? multiplexStrlen30(zName) : 0; sz = sizeof(multiplexGroup) /* multiplexGroup */ + nName + 1; /* zName */ pGroup = sqlite3_malloc( sz ); @@ -495,32 +417,34 @@ static int multiplexOpen( if( rc==SQLITE_OK ){ /* assign pointers to extra space allocated */ - char *p = (char *)&pGroup[1]; - pMultiplexOpen->pGroup = pGroup; memset(pGroup, 0, sz); + pMultiplexOpen->pGroup = pGroup; pGroup->bEnabled = -1; pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE; - if( flags & SQLITE_OPEN_URI ){ - const char *zChunkSize; - zChunkSize = sqlite3_uri_parameter(zName, "chunksize"); - if( zChunkSize ){ - unsigned int n = 0; - int i; - for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){ - n = n*10 + zChunkSize[i] - '0'; - } - if( n>0 ){ - pGroup->szChunk = (n+0xffff)&~0xffff; - }else{ - /* A zero or negative chunksize disabled the multiplexor */ - pGroup->bEnabled = 0; + + if( zName ){ + char *p = (char *)&pGroup[1]; + if( flags & SQLITE_OPEN_URI ){ + const char *zChunkSize; + zChunkSize = sqlite3_uri_parameter(zName, "chunksize"); + if( zChunkSize ){ + unsigned int n = 0; + int i; + for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){ + n = n*10 + zChunkSize[i] - '0'; + } + if( n>0 ){ + pGroup->szChunk = (n+0xffff)&~0xffff; + }else{ + /* A zero or negative chunksize disabled the multiplexor */ + pGroup->bEnabled = 0; + } } } + pGroup->zName = p; + memcpy(pGroup->zName, zName, nName+1); + pGroup->nName = nName; } - pGroup->zName = p; - /* save off base filename, name length, and original open flags */ - memcpy(pGroup->zName, zName, nName+1); - pGroup->nName = nName; pGroup->flags = flags; rc = multiplexSubFilename(pGroup, 1); if( rc==SQLITE_OK ){ @@ -796,7 +720,6 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; - int rc2; int i; multiplexEnter(); if( !pGroup->bEnabled ){ @@ -809,38 +732,32 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ }else{ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; *pSize = 0; - for(i=0; 1; i++){ + for(i=0; rc==SQLITE_OK; i++){ sqlite3_file *pSubOpen = 0; int exists = 0; rc = multiplexSubFilename(pGroup, i); - if( rc ) break; - if( pGroup->flags & SQLITE_OPEN_DELETEONCLOSE ){ - exists = pGroup->nReal>=i && pGroup->aReal[i].p!=0; - rc2 = SQLITE_OK; - }else{ - rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z, - SQLITE_ACCESS_EXISTS, &exists); + if( rc!=SQLITE_OK ) break; + if( pGroup->nReal>i && pGroup->aReal[i].p!=0 ){ + exists = 1; + }else if( (pGroup->flags & SQLITE_OPEN_DELETEONCLOSE)==0 ){ + const char *zReal = pGroup->aReal[i].z; + rc = pOrigVfs->xAccess(pOrigVfs, zReal, SQLITE_ACCESS_EXISTS, &exists); } - if( rc2==SQLITE_OK && exists){ - /* if it exists, open it */ + if( exists==0 ){ + /* stop at first "gap" or IO error. */ + break; + } + if( rc==SQLITE_OK ){ pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); - }else{ - /* stop at first "gap" */ - break; } - if( pSubOpen ){ - sqlite3_int64 sz; - rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); - if( rc2!=SQLITE_OK ){ - rc = rc2; - }else{ - if( sz>pGroup->szChunk ){ - rc = SQLITE_IOERR_FSTAT; - } - *pSize += sz; + assert( pSubOpen || rc!=SQLITE_OK ); + if( rc==SQLITE_OK ){ + sqlite3_int64 sz = 0; + rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); + if( rc==SQLITE_OK && sz>pGroup->szChunk ){ + rc = SQLITE_IOERR_FSTAT; } - }else{ - break; + *pSize += sz; } } } @@ -1191,9 +1108,13 @@ static int test_multiplex_dump( for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){ pGroupTerm = Tcl_NewObj(); - pGroup->zName[pGroup->nName] = '\0'; - Tcl_ListObjAppendElement(interp, pGroupTerm, + if( pGroup->zName ){ + pGroup->zName[pGroup->nName] = '\0'; + Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewStringObj(pGroup->zName, -1)); + }else{ + Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj()); + } Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->nName)); Tcl_ListObjAppendElement(interp, pGroupTerm, diff --git a/test/multiplex.test b/test/multiplex.test index cb6c8a0b63..7168e753ab 100644 --- a/test/multiplex.test +++ b/test/multiplex.test @@ -14,6 +14,16 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl +# The tests in this file assume that SQLite is compiled without +# ENABLE_8_3_NAMES. +# +ifcapable 8_3_names { + puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. " + puts "Skipping tests multiplex-*." + finish_test + return +} + set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ] set g_max_chunks 32 diff --git a/test/multiplex3.test b/test/multiplex3.test new file mode 100644 index 0000000000..b5a2f1de73 --- /dev/null +++ b/test/multiplex3.test @@ -0,0 +1,98 @@ + +# 2011 December 13 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file contains tests for error (IO, OOM etc.) handling when using +# the multiplexor extension with 8.3 filenames. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set ::testprefix multiplex3 + +ifcapable !8_3_names { + puts -nonewline "SQLite compiled without SQLITE_ENABLE_8_3_NAMES. " + puts "Skipping tests multiplex3-*." + finish_test + return +} + +db close +sqlite3_shutdown +sqlite3_config_uri 1 +autoinstall_test_functions + +sqlite3_multiplex_initialize "" 1 + +proc destroy_vfs_stack {} { + generic_unregister stack + sqlite3_multiplex_shutdown +} + +proc multiplex_delete_db {} { + forcedelete test.db + for {set i 1} {$i <= 1000} {incr i} { + forcedelete test.[format %03d $i] + } +} + +# Procs to save and restore the current muliplexed database. +# +proc multiplex_save_db {} { + foreach f [glob -nocomplain sv_test.*] { forcedelete $f } + foreach f [glob -nocomplain test.*] { forcecopy $f "sv_$f" } +} +proc multiplex_restore_db {} { + foreach f [glob -nocomplain test.*] {forcedelete $f} + foreach f [glob -nocomplain sv_test.*] {forcecopy $f [string range $f 3 end]} } + + +do_test 1.0 { + multiplex_delete_db + sqlite3 db file:test.db?8_3_names=1 + sqlite3_multiplex_control db main chunk_size [expr 256*1024] + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES(randomblob(15), randomblob(2000)); + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 2 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 4 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 8 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 16 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 32 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 64 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 128 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 256 + INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 512 + } + set ::cksum1 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}] + db close + multiplex_save_db +} {} + +do_faultsim_test 1 -prep { + multiplex_restore_db + sqlite3 db file:test.db?8_3_names=1 + sqlite3_multiplex_control db main chunk_size [expr 256*1024] +} -body { + execsql "UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0" +} -test { + faultsim_test_result {0 {}} + if {$testrc!=0} { + set cksum2 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}] + if {$cksum2 != $::cksum1} { error "data mismatch" } + } +} + +catch { db close } + +sqlite3_multiplex_shutdown +finish_test