From: drh Date: Tue, 2 Jan 2018 16:02:50 +0000 (+0000) Subject: Enhance the memvfs extension so that it can be read/write. X-Git-Tag: version-3.22.0~116 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=595a0e2a4a5d6781abaebd4f0da2720568e1c5bb;p=thirdparty%2Fsqlite.git Enhance the memvfs extension so that it can be read/write. FossilOrigin-Name: 04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 --- diff --git a/ext/misc/memvfs.c b/ext/misc/memvfs.c index 62a8a033d7..27a61c35e4 100644 --- a/ext/misc/memvfs.c +++ b/ext/misc/memvfs.c @@ -10,23 +10,33 @@ ** ****************************************************************************** ** -** This is an in-memory read-only VFS implementation. The application -** supplies a block of memory which is the database file, and this VFS -** uses that block of memory. +** This is an in-memory VFS implementation. The application supplies +** a chunk of memory to hold the database file. ** -** Because there is no place to store journals and no good way to lock -** the "file", this VFS is read-only. +** Because there is place to store a rollback or wal journal, the database +** must use one of journal_mode=MEMORY or journal_mode=NONE. ** ** USAGE: ** -** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336", &db, -** SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, +** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336&max=65536", &db, +** SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, ** "memvfs"); ** -** The ptr= and sz= query parameters are required or the open will fail. -** The ptr= parameter gives the memory address of the buffer holding the -** read-only database and sz= gives the size of the database. The parameter -** values may be in hexadecimal or decimal. The filename is ignored. +** These are the query parameters: +** +** ptr= The address of the memory buffer that holds the database. +** +** sz= The current size the database file +** +** maxsz= The maximum size of the database. In other words, the +** amount of space allocated for the ptr= buffer. +** +** freeonclose= If true, then sqlite3_free() is called on the ptr= +** value when the connection closes. +** +** The ptr= and sz= query parameters are required. If maxsz= is omitted, +** then it defaults to the sz= value. Parameter values can be in either +** decimal or hexadecimal. The filename in the URI is ignored. */ #include SQLITE_EXTENSION_INIT1 @@ -49,7 +59,9 @@ typedef struct MemFile MemFile; struct MemFile { sqlite3_file base; /* IO methods */ sqlite3_int64 sz; /* Size of the file */ + sqlite3_int64 szMax; /* Space allocated to aData */ unsigned char *aData; /* content of the file */ + int bFreeOnClose; /* Invoke sqlite3_free() on aData at close */ }; /* @@ -144,6 +156,8 @@ static const sqlite3_io_methods mem_io_methods = { ** to free. */ static int memClose(sqlite3_file *pFile){ + MemFile *p = (MemFile *)pFile; + if( p->bFreeOnClose ) sqlite3_free(p->aData); return SQLITE_OK; } @@ -170,21 +184,34 @@ static int memWrite( int iAmt, sqlite_int64 iOfst ){ - return SQLITE_READONLY; + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + if( iOfst+iAmt>p->szMax ) return SQLITE_FULL; + if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); + p->sz = iOfst+iAmt; + } + memcpy(p->aData+iOfst, z, iAmt); + return SQLITE_OK; } /* ** Truncate an mem-file. */ static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){ - return SQLITE_READONLY; + MemFile *p = (MemFile *)pFile; + if( size>p->sz ){ + if( size>p->szMax ) return SQLITE_FULL; + memset(p->aData+p->sz, 0, size-p->sz); + } + p->sz = size; + return SQLITE_OK; } /* ** Sync an mem-file. */ static int memSync(sqlite3_file *pFile, int flags){ - return SQLITE_READONLY; + return SQLITE_OK; } /* @@ -200,7 +227,7 @@ static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ** Lock an mem-file. */ static int memLock(sqlite3_file *pFile, int eLock){ - return SQLITE_READONLY; + return SQLITE_OK; } /* @@ -242,7 +269,10 @@ static int memSectorSize(sqlite3_file *pFile){ ** Return the device characteristic flags supported by an mem-file. */ static int memDeviceCharacteristics(sqlite3_file *pFile){ - return SQLITE_IOCAP_IMMUTABLE; + return SQLITE_IOCAP_ATOMIC | + SQLITE_IOCAP_POWERSAFE_OVERWRITE | + SQLITE_IOCAP_SAFE_APPEND | + SQLITE_IOCAP_SEQUENTIAL; } /* Create a shared memory file mapping */ @@ -253,12 +283,12 @@ static int memShmMap( int bExtend, void volatile **pp ){ - return SQLITE_READONLY; + return SQLITE_IOERR_SHMMAP; } /* Perform locking on a shared-memory segment */ static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){ - return SQLITE_READONLY; + return SQLITE_IOERR_SHMLOCK; } /* Memory barrier operation on shared memory */ @@ -305,6 +335,9 @@ static int memOpen( if( p->aData==0 ) return SQLITE_CANTOPEN; p->sz = sqlite3_uri_int64(zName,"sz",0); if( p->sz<0 ) return SQLITE_CANTOPEN; + p->szMax = sqlite3_uri_int64(zName,"max",p->sz); + if( p->szMaxsz ) return SQLITE_CANTOPEN; + p->bFreeOnClose = sqlite3_uri_boolean(zName,"freeonclose",0); pFile->pMethods = &mem_io_methods; return SQLITE_OK; } @@ -315,7 +348,7 @@ static int memOpen( ** returning. */ static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return SQLITE_READONLY; + return SQLITE_IOERR_DELETE; } /* @@ -328,14 +361,7 @@ static int memAccess( int flags, int *pResOut ){ - /* The spec says there are three possible values for flags. But only - ** two of them are actually used */ - assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); - if( flags==SQLITE_ACCESS_READWRITE ){ - *pResOut = 0; - }else{ - *pResOut = 1; - } + *pResOut = 0; return SQLITE_OK; } @@ -416,31 +442,43 @@ static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ #ifdef MEMVFS_TEST /* -** memload(FILENAME) +** memvfs_from_file(FILENAME, MAXSIZE) ** ** This an SQL function used to help in testing the memvfs VFS. The ** function reads the content of a file into memory and then returns -** a string that gives the locate and size of the in-memory buffer. +** a URI that can be handed to ATTACH to attach the memory buffer as +** a database. Example: +** +** ATTACH memvfs_from_file('test.db',1048576) AS inmem; +** +** The optional MAXSIZE argument gives the size of the memory allocation +** used to hold the database. If omitted, it defaults to the size of the +** file on disk. */ #include -static void memvfsMemloadFunc( +static void memvfsFromFileFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ unsigned char *p; sqlite3_int64 sz; + sqlite3_int64 szMax; FILE *in; const char *zFilename = (const char*)sqlite3_value_text(argv[0]); - char zReturn[100]; + char *zUri; if( zFilename==0 ) return; in = fopen(zFilename, "rb"); if( in==0 ) return; fseek(in, 0, SEEK_END); - sz = ftell(in); + szMax = sz = ftell(in); rewind(in); - p = sqlite3_malloc( sz ); + if( argc>=2 ){ + szMax = sqlite3_value_int64(argv[1]); + if( szMaxzName,"memvfs")!=0 ) return; + rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); + if( rc ) return; + fwrite(p->aData, 1, (size_t)p->sz, out); + fclose(out); +} +#endif /* MEMVFS_TEST */ + +#ifdef MEMVFS_TEST /* Called for each new database connection */ static int memvfsRegister( sqlite3 *db, - const char **pzErrMsg, + char **pzErrMsg, const struct sqlite3_api_routines *pThunk ){ - return sqlite3_create_function(db, "memload", 1, SQLITE_UTF8, 0, - memvfsMemloadFunc, 0, 0); + sqlite3_create_function(db, "memvfs_from_file", 1, SQLITE_UTF8, 0, + memvfsFromFileFunc, 0, 0); + sqlite3_create_function(db, "memvfs_from_file", 2, SQLITE_UTF8, 0, + memvfsFromFileFunc, 0, 0); + sqlite3_create_function(db, "memvfs_to_file", 2, SQLITE_UTF8, 0, + memvfsToFileFunc, 0, 0); + return SQLITE_OK; } #endif /* MEMVFS_TEST */ @@ -485,6 +565,9 @@ int sqlite3_memvfs_init( if( rc==SQLITE_OK ){ rc = sqlite3_auto_extension((void(*)(void))memvfsRegister); } + if( rc==SQLITE_OK ){ + rc = memvfsRegister(db, pzErrMsg, pApi); + } #endif if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; return rc; diff --git a/manifest b/manifest index 8af4fc7c93..b3405dc4c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\ssqlite3_file_control()\sdocumentation.\s\sNo\schanges\sto\scode. -D 2018-01-02T13:48:48.784 +C Enhance\sthe\smemvfs\sextension\sso\sthat\sit\scan\sbe\sread/write. +D 2018-01-02T16:02:50.552 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -278,7 +278,7 @@ F ext/misc/fileio.c b1aa06c0f1dac277695d4529e5e976c65ab5678dcbb53a0304deaa8adc44 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984 -F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33 +F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 -R 1ce62a1c4d9b56a67e8d1f1aed222781 +P 240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a +R e6325f7b9d9fed8be88a348d63977f27 U drh -Z d9ace2c20dd904e2b4c8de8f33d7aa5e +Z de6d00886014fb58a1b54f4eb1670d54 diff --git a/manifest.uuid b/manifest.uuid index 3dd953071f..c9ede0a08a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a \ No newline at end of file +04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 \ No newline at end of file