1ac442f41Sdrh /*
2ac442f41Sdrh ** 2016-09-07
3ac442f41Sdrh **
4ac442f41Sdrh ** The author disclaims copyright to this source code. In place of
5ac442f41Sdrh ** a legal notice, here is a blessing:
6ac442f41Sdrh **
7ac442f41Sdrh ** May you do good and not evil.
8ac442f41Sdrh ** May you find forgiveness for yourself and forgive others.
9ac442f41Sdrh ** May you share freely, never taking more than you give.
10ac442f41Sdrh **
11ac442f41Sdrh ******************************************************************************
12ac442f41Sdrh **
13840fda48Sdrh ** This file implements an in-memory VFS. A database is held as a contiguous
1499abe5c4Sdrh ** block of memory.
1599abe5c4Sdrh **
1699abe5c4Sdrh ** This file also implements interface sqlite3_serialize() and
1799abe5c4Sdrh ** sqlite3_deserialize().
18ac442f41Sdrh */
19ac442f41Sdrh #include "sqliteInt.h"
208d889afcSdrh #ifndef SQLITE_OMIT_DESERIALIZE
21ac442f41Sdrh
22ac442f41Sdrh /*
23ac442f41Sdrh ** Forward declaration of objects used by this utility
24ac442f41Sdrh */
25ac442f41Sdrh typedef struct sqlite3_vfs MemVfs;
26ac442f41Sdrh typedef struct MemFile MemFile;
272f4d0ec3Sdrh typedef struct MemStore MemStore;
28ac442f41Sdrh
29ac442f41Sdrh /* Access to a lower-level VFS that (might) implement dynamic loading,
30ac442f41Sdrh ** access to randomness, etc.
31ac442f41Sdrh */
32ac442f41Sdrh #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
33ac442f41Sdrh
342f4d0ec3Sdrh /* Storage for a memdb file.
352f4d0ec3Sdrh **
362f4d0ec3Sdrh ** An memdb object can be shared or separate. Shared memdb objects can be
372f4d0ec3Sdrh ** used by more than one database connection. Mutexes are used by shared
382f4d0ec3Sdrh ** memdb objects to coordinate access. Separate memdb objects are only
392f4d0ec3Sdrh ** connected to a single database connection and do not require additional
402f4d0ec3Sdrh ** mutexes.
412f4d0ec3Sdrh **
422f4d0ec3Sdrh ** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
432f4d0ec3Sdrh ** using "file:/name?vfs=memdb". The first character of the name must be
442f4d0ec3Sdrh ** "/" or else the object will be a separate memdb object. All shared
452f4d0ec3Sdrh ** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
462f4d0ec3Sdrh **
472f4d0ec3Sdrh ** Separate memdb objects are created using a name that does not begin
482f4d0ec3Sdrh ** with "/" or using sqlite3_deserialize().
492f4d0ec3Sdrh **
502f4d0ec3Sdrh ** Access rules for shared MemStore objects:
512f4d0ec3Sdrh **
522f4d0ec3Sdrh ** * .zFName is initialized when the object is created and afterwards
532f4d0ec3Sdrh ** is unchanged until the object is destroyed. So it can be accessed
542f4d0ec3Sdrh ** at any time as long as we know the object is not being destroyed,
552f4d0ec3Sdrh ** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
562f4d0ec3Sdrh ** .pMutex is held or the object is not part of memdb_g.apMemStore[].
572f4d0ec3Sdrh **
582f4d0ec3Sdrh ** * Can .pMutex can only be changed while holding the
592f4d0ec3Sdrh ** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
602f4d0ec3Sdrh ** of memdb_g.apMemStore[].
612f4d0ec3Sdrh **
622f4d0ec3Sdrh ** * Other fields can only be changed while holding the .pMutex mutex
632f4d0ec3Sdrh ** or when the .nRef is less than zero and the object is not part of
642f4d0ec3Sdrh ** memdb_g.apMemStore[].
652f4d0ec3Sdrh **
662f4d0ec3Sdrh ** * The .aData pointer has the added requirement that it can can only
672f4d0ec3Sdrh ** be changed (for resizing) when nMmap is zero.
682f4d0ec3Sdrh **
692f4d0ec3Sdrh */
702f4d0ec3Sdrh struct MemStore {
71ac442f41Sdrh sqlite3_int64 sz; /* Size of the file */
726ca64481Sdrh sqlite3_int64 szAlloc; /* Space allocated to aData */
736ca64481Sdrh sqlite3_int64 szMax; /* Maximum allowed size of the file */
74ac442f41Sdrh unsigned char *aData; /* content of the file */
752f4d0ec3Sdrh sqlite3_mutex *pMutex; /* Used by shared stores only */
76ac442f41Sdrh int nMmap; /* Number of memory mapped pages */
77ac442f41Sdrh unsigned mFlags; /* Flags */
782f4d0ec3Sdrh int nRdLock; /* Number of readers */
792f4d0ec3Sdrh int nWrLock; /* Number of writers. (Always 0 or 1) */
802f4d0ec3Sdrh int nRef; /* Number of users of this MemStore */
812f4d0ec3Sdrh char *zFName; /* The filename for shared stores */
822f4d0ec3Sdrh };
832f4d0ec3Sdrh
842f4d0ec3Sdrh /* An open file */
852f4d0ec3Sdrh struct MemFile {
862f4d0ec3Sdrh sqlite3_file base; /* IO methods */
872f4d0ec3Sdrh MemStore *pStore; /* The storage */
88ac442f41Sdrh int eLock; /* Most recent lock against this file */
89ac442f41Sdrh };
90ac442f41Sdrh
91ac442f41Sdrh /*
9299bd5525Slarrybr ** File-scope variables for holding the memdb files that are accessible
932f4d0ec3Sdrh ** to multiple database connections in separate threads.
942f4d0ec3Sdrh **
952f4d0ec3Sdrh ** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
962f4d0ec3Sdrh */
9799bd5525Slarrybr static struct MemFS {
982f4d0ec3Sdrh int nMemStore; /* Number of shared MemStore objects */
992f4d0ec3Sdrh MemStore **apMemStore; /* Array of all shared MemStore objects */
1002f4d0ec3Sdrh } memdb_g;
1012f4d0ec3Sdrh
1022f4d0ec3Sdrh /*
103ac442f41Sdrh ** Methods for MemFile
104ac442f41Sdrh */
105ac442f41Sdrh static int memdbClose(sqlite3_file*);
106ac442f41Sdrh static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
107ac442f41Sdrh static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
108ac442f41Sdrh static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
109ac442f41Sdrh static int memdbSync(sqlite3_file*, int flags);
110ac442f41Sdrh static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
111ac442f41Sdrh static int memdbLock(sqlite3_file*, int);
11214714167Sdrh /* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
113ac442f41Sdrh static int memdbFileControl(sqlite3_file*, int op, void *pArg);
1145f9d192dSdrh /* static int memdbSectorSize(sqlite3_file*); // not used */
115ac442f41Sdrh static int memdbDeviceCharacteristics(sqlite3_file*);
116ac442f41Sdrh static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
117ac442f41Sdrh static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
118ac442f41Sdrh
119ac442f41Sdrh /*
120ac442f41Sdrh ** Methods for MemVfs
121ac442f41Sdrh */
122ac442f41Sdrh static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
12314714167Sdrh /* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
124ac442f41Sdrh static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
125ac442f41Sdrh static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
126ac442f41Sdrh static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
127ac442f41Sdrh static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
128ac442f41Sdrh static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
129ac442f41Sdrh static void memdbDlClose(sqlite3_vfs*, void*);
130ac442f41Sdrh static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
131ac442f41Sdrh static int memdbSleep(sqlite3_vfs*, int microseconds);
13214714167Sdrh /* static int memdbCurrentTime(sqlite3_vfs*, double*); */
133ac442f41Sdrh static int memdbGetLastError(sqlite3_vfs*, int, char *);
134ac442f41Sdrh static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
135ac442f41Sdrh
136ac442f41Sdrh static sqlite3_vfs memdb_vfs = {
137ac442f41Sdrh 2, /* iVersion */
138ac442f41Sdrh 0, /* szOsFile (set when registered) */
139ac442f41Sdrh 1024, /* mxPathname */
140ac442f41Sdrh 0, /* pNext */
141ac442f41Sdrh "memdb", /* zName */
142ac442f41Sdrh 0, /* pAppData (set when registered) */
143ac442f41Sdrh memdbOpen, /* xOpen */
14414714167Sdrh 0, /* memdbDelete, */ /* xDelete */
145ac442f41Sdrh memdbAccess, /* xAccess */
146ac442f41Sdrh memdbFullPathname, /* xFullPathname */
147ac442f41Sdrh memdbDlOpen, /* xDlOpen */
148ac442f41Sdrh memdbDlError, /* xDlError */
149ac442f41Sdrh memdbDlSym, /* xDlSym */
150ac442f41Sdrh memdbDlClose, /* xDlClose */
151ac442f41Sdrh memdbRandomness, /* xRandomness */
152ac442f41Sdrh memdbSleep, /* xSleep */
15314714167Sdrh 0, /* memdbCurrentTime, */ /* xCurrentTime */
154ac442f41Sdrh memdbGetLastError, /* xGetLastError */
155904e48ebSdrh memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
156904e48ebSdrh 0, /* xSetSystemCall */
157904e48ebSdrh 0, /* xGetSystemCall */
158904e48ebSdrh 0, /* xNextSystemCall */
159ac442f41Sdrh };
160ac442f41Sdrh
161ac442f41Sdrh static const sqlite3_io_methods memdb_io_methods = {
162ac442f41Sdrh 3, /* iVersion */
163ac442f41Sdrh memdbClose, /* xClose */
164ac442f41Sdrh memdbRead, /* xRead */
165ac442f41Sdrh memdbWrite, /* xWrite */
166ac442f41Sdrh memdbTruncate, /* xTruncate */
167ac442f41Sdrh memdbSync, /* xSync */
168ac442f41Sdrh memdbFileSize, /* xFileSize */
169ac442f41Sdrh memdbLock, /* xLock */
170ac442f41Sdrh memdbLock, /* xUnlock - same as xLock in this case */
17114714167Sdrh 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
172ac442f41Sdrh memdbFileControl, /* xFileControl */
1735f9d192dSdrh 0, /* memdbSectorSize,*/ /* xSectorSize */
174ac442f41Sdrh memdbDeviceCharacteristics, /* xDeviceCharacteristics */
17599abe5c4Sdrh 0, /* xShmMap */
17699abe5c4Sdrh 0, /* xShmLock */
17799abe5c4Sdrh 0, /* xShmBarrier */
17899abe5c4Sdrh 0, /* xShmUnmap */
179ac442f41Sdrh memdbFetch, /* xFetch */
180ac442f41Sdrh memdbUnfetch /* xUnfetch */
181ac442f41Sdrh };
182ac442f41Sdrh
1832f4d0ec3Sdrh /*
1842f4d0ec3Sdrh ** Enter/leave the mutex on a MemStore
1852f4d0ec3Sdrh */
186904e48ebSdrh #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
memdbEnter(MemStore * p)187904e48ebSdrh static void memdbEnter(MemStore *p){
188904e48ebSdrh UNUSED_PARAMETER(p);
189904e48ebSdrh }
memdbLeave(MemStore * p)190904e48ebSdrh static void memdbLeave(MemStore *p){
191904e48ebSdrh UNUSED_PARAMETER(p);
192904e48ebSdrh }
193904e48ebSdrh #else
memdbEnter(MemStore * p)1942f4d0ec3Sdrh static void memdbEnter(MemStore *p){
1952f4d0ec3Sdrh sqlite3_mutex_enter(p->pMutex);
1962f4d0ec3Sdrh }
memdbLeave(MemStore * p)1972f4d0ec3Sdrh static void memdbLeave(MemStore *p){
1982f4d0ec3Sdrh sqlite3_mutex_leave(p->pMutex);
1992f4d0ec3Sdrh }
200904e48ebSdrh #endif
2012f4d0ec3Sdrh
202ac442f41Sdrh
203ac442f41Sdrh
204ac442f41Sdrh /*
205ac442f41Sdrh ** Close an memdb-file.
2062f4d0ec3Sdrh ** Free the underlying MemStore object when its refcount drops to zero
2072f4d0ec3Sdrh ** or less.
208ac442f41Sdrh */
memdbClose(sqlite3_file * pFile)209ac442f41Sdrh static int memdbClose(sqlite3_file *pFile){
2102f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
2112f4d0ec3Sdrh if( p->zFName ){
2122f4d0ec3Sdrh int i;
2132d344f94Sdrh #ifndef SQLITE_MUTEX_OMIT
2142f4d0ec3Sdrh sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
2152d344f94Sdrh #endif
2162f4d0ec3Sdrh sqlite3_mutex_enter(pVfsMutex);
2172f4d0ec3Sdrh for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
2182f4d0ec3Sdrh if( memdb_g.apMemStore[i]==p ){
21952d14078Sdrh memdbEnter(p);
22052d14078Sdrh if( p->nRef==1 ){
2212f4d0ec3Sdrh memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
2222f4d0ec3Sdrh if( memdb_g.nMemStore==0 ){
2232f4d0ec3Sdrh sqlite3_free(memdb_g.apMemStore);
2242f4d0ec3Sdrh memdb_g.apMemStore = 0;
2252f4d0ec3Sdrh }
22652d14078Sdrh }
2272f4d0ec3Sdrh break;
2282f4d0ec3Sdrh }
2292f4d0ec3Sdrh }
2302f4d0ec3Sdrh sqlite3_mutex_leave(pVfsMutex);
23152d14078Sdrh }else{
23252d14078Sdrh memdbEnter(p);
23352d14078Sdrh }
23452d14078Sdrh p->nRef--;
23552d14078Sdrh if( p->nRef<=0 ){
23652d14078Sdrh if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
23752d14078Sdrh sqlite3_free(p->aData);
2382f4d0ec3Sdrh }
2392f4d0ec3Sdrh memdbLeave(p);
2402f4d0ec3Sdrh sqlite3_mutex_free(p->pMutex);
2412f4d0ec3Sdrh sqlite3_free(p);
2422f4d0ec3Sdrh }else{
2432f4d0ec3Sdrh memdbLeave(p);
2442f4d0ec3Sdrh }
245ac442f41Sdrh return SQLITE_OK;
246ac442f41Sdrh }
247ac442f41Sdrh
248ac442f41Sdrh /*
249ac442f41Sdrh ** Read data from an memdb-file.
250ac442f41Sdrh */
memdbRead(sqlite3_file * pFile,void * zBuf,int iAmt,sqlite_int64 iOfst)251ac442f41Sdrh static int memdbRead(
252ac442f41Sdrh sqlite3_file *pFile,
253ac442f41Sdrh void *zBuf,
254ac442f41Sdrh int iAmt,
255ac442f41Sdrh sqlite_int64 iOfst
256ac442f41Sdrh ){
2572f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
2582f4d0ec3Sdrh memdbEnter(p);
259ac442f41Sdrh if( iOfst+iAmt>p->sz ){
260ac442f41Sdrh memset(zBuf, 0, iAmt);
261cb7d541dSdrh if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
2622f4d0ec3Sdrh memdbLeave(p);
263ac442f41Sdrh return SQLITE_IOERR_SHORT_READ;
264ac442f41Sdrh }
265ac442f41Sdrh memcpy(zBuf, p->aData+iOfst, iAmt);
2662f4d0ec3Sdrh memdbLeave(p);
267ac442f41Sdrh return SQLITE_OK;
268ac442f41Sdrh }
269ac442f41Sdrh
270ac442f41Sdrh /*
271ac442f41Sdrh ** Try to enlarge the memory allocation to hold at least sz bytes
272ac442f41Sdrh */
memdbEnlarge(MemStore * p,sqlite3_int64 newSz)2732f4d0ec3Sdrh static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
274ac442f41Sdrh unsigned char *pNew;
27588944e6fSdrh if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
2765f9d192dSdrh return SQLITE_FULL;
2775f9d192dSdrh }
2786ca64481Sdrh if( newSz>p->szMax ){
2796ca64481Sdrh return SQLITE_FULL;
2806ca64481Sdrh }
2816ca64481Sdrh newSz *= 2;
2826ca64481Sdrh if( newSz>p->szMax ) newSz = p->szMax;
283d924e7bcSdrh pNew = sqlite3Realloc(p->aData, newSz);
284a3a91dd5Sdan if( pNew==0 ) return SQLITE_IOERR_NOMEM;
285ac442f41Sdrh p->aData = pNew;
2866ca64481Sdrh p->szAlloc = newSz;
287ac442f41Sdrh return SQLITE_OK;
288ac442f41Sdrh }
289ac442f41Sdrh
290ac442f41Sdrh /*
291ac442f41Sdrh ** Write data to an memdb-file.
292ac442f41Sdrh */
memdbWrite(sqlite3_file * pFile,const void * z,int iAmt,sqlite_int64 iOfst)293ac442f41Sdrh static int memdbWrite(
294ac442f41Sdrh sqlite3_file *pFile,
295ac442f41Sdrh const void *z,
296ac442f41Sdrh int iAmt,
297ac442f41Sdrh sqlite_int64 iOfst
298ac442f41Sdrh ){
2992f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
3002f4d0ec3Sdrh memdbEnter(p);
301483051c9Sdrh if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
302483051c9Sdrh /* Can't happen: memdbLock() will return SQLITE_READONLY before
303483051c9Sdrh ** reaching this point */
3042f4d0ec3Sdrh memdbLeave(p);
3052f4d0ec3Sdrh return SQLITE_IOERR_WRITE;
3062f4d0ec3Sdrh }
307ac442f41Sdrh if( iOfst+iAmt>p->sz ){
3085f9d192dSdrh int rc;
3096ca64481Sdrh if( iOfst+iAmt>p->szAlloc
3106ca64481Sdrh && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
3115f9d192dSdrh ){
3122f4d0ec3Sdrh memdbLeave(p);
3135f9d192dSdrh return rc;
314ac442f41Sdrh }
315ac442f41Sdrh if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
316ac442f41Sdrh p->sz = iOfst+iAmt;
317ac442f41Sdrh }
318ac442f41Sdrh memcpy(p->aData+iOfst, z, iAmt);
3192f4d0ec3Sdrh memdbLeave(p);
320ac442f41Sdrh return SQLITE_OK;
321ac442f41Sdrh }
322ac442f41Sdrh
323ac442f41Sdrh /*
324ac442f41Sdrh ** Truncate an memdb-file.
32514714167Sdrh **
32614714167Sdrh ** In rollback mode (which is always the case for memdb, as it does not
32714714167Sdrh ** support WAL mode) the truncate() method is only used to reduce
32814714167Sdrh ** the size of a file, never to increase the size.
329ac442f41Sdrh */
memdbTruncate(sqlite3_file * pFile,sqlite_int64 size)330ac442f41Sdrh static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
3312f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
3322f4d0ec3Sdrh int rc = SQLITE_OK;
3332f4d0ec3Sdrh memdbEnter(p);
334*1a39e456Sdan if( size>p->sz ){
335*1a39e456Sdan /* This can only happen with a corrupt wal mode db */
336*1a39e456Sdan rc = SQLITE_CORRUPT;
3372f4d0ec3Sdrh }else{
338ac442f41Sdrh p->sz = size;
3392f4d0ec3Sdrh }
3402f4d0ec3Sdrh memdbLeave(p);
3412f4d0ec3Sdrh return rc;
342ac442f41Sdrh }
343ac442f41Sdrh
344ac442f41Sdrh /*
345ac442f41Sdrh ** Sync an memdb-file.
346ac442f41Sdrh */
memdbSync(sqlite3_file * pFile,int flags)347ac442f41Sdrh static int memdbSync(sqlite3_file *pFile, int flags){
348904e48ebSdrh UNUSED_PARAMETER(pFile);
349904e48ebSdrh UNUSED_PARAMETER(flags);
350ac442f41Sdrh return SQLITE_OK;
351ac442f41Sdrh }
352ac442f41Sdrh
353ac442f41Sdrh /*
354ac442f41Sdrh ** Return the current file-size of an memdb-file.
355ac442f41Sdrh */
memdbFileSize(sqlite3_file * pFile,sqlite_int64 * pSize)356ac442f41Sdrh static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3572f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
3582f4d0ec3Sdrh memdbEnter(p);
359ac442f41Sdrh *pSize = p->sz;
3602f4d0ec3Sdrh memdbLeave(p);
361ac442f41Sdrh return SQLITE_OK;
362ac442f41Sdrh }
363ac442f41Sdrh
364ac442f41Sdrh /*
365ac442f41Sdrh ** Lock an memdb-file.
366ac442f41Sdrh */
memdbLock(sqlite3_file * pFile,int eLock)367ac442f41Sdrh static int memdbLock(sqlite3_file *pFile, int eLock){
3682f4d0ec3Sdrh MemFile *pThis = (MemFile*)pFile;
3692f4d0ec3Sdrh MemStore *p = pThis->pStore;
3702f4d0ec3Sdrh int rc = SQLITE_OK;
3712f4d0ec3Sdrh if( eLock==pThis->eLock ) return SQLITE_OK;
3722f4d0ec3Sdrh memdbEnter(p);
3732f4d0ec3Sdrh if( eLock>SQLITE_LOCK_SHARED ){
3742f4d0ec3Sdrh if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
3752f4d0ec3Sdrh rc = SQLITE_READONLY;
3762f4d0ec3Sdrh }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
3772f4d0ec3Sdrh if( p->nWrLock ){
3782f4d0ec3Sdrh rc = SQLITE_BUSY;
3792f4d0ec3Sdrh }else{
3802f4d0ec3Sdrh p->nWrLock = 1;
381f186f0b0Sdrh }
3822f4d0ec3Sdrh }
3832f4d0ec3Sdrh }else if( eLock==SQLITE_LOCK_SHARED ){
3842f4d0ec3Sdrh if( pThis->eLock > SQLITE_LOCK_SHARED ){
3852f4d0ec3Sdrh assert( p->nWrLock==1 );
3862f4d0ec3Sdrh p->nWrLock = 0;
3872f4d0ec3Sdrh }else if( p->nWrLock ){
3882f4d0ec3Sdrh rc = SQLITE_BUSY;
3892f4d0ec3Sdrh }else{
3902f4d0ec3Sdrh p->nRdLock++;
3912f4d0ec3Sdrh }
3922f4d0ec3Sdrh }else{
3932f4d0ec3Sdrh assert( eLock==SQLITE_LOCK_NONE );
3942f4d0ec3Sdrh if( pThis->eLock>SQLITE_LOCK_SHARED ){
3952f4d0ec3Sdrh assert( p->nWrLock==1 );
3962f4d0ec3Sdrh p->nWrLock = 0;
3972f4d0ec3Sdrh }
3982f4d0ec3Sdrh assert( p->nRdLock>0 );
3992f4d0ec3Sdrh p->nRdLock--;
4002f4d0ec3Sdrh }
4012f4d0ec3Sdrh if( rc==SQLITE_OK ) pThis->eLock = eLock;
4022f4d0ec3Sdrh memdbLeave(p);
4032f4d0ec3Sdrh return rc;
404ac442f41Sdrh }
405ac442f41Sdrh
4062f4d0ec3Sdrh #if 0
407ac442f41Sdrh /*
4082f4d0ec3Sdrh ** This interface is only used for crash recovery, which does not
4092f4d0ec3Sdrh ** occur on an in-memory database.
410ac442f41Sdrh */
411ac442f41Sdrh static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
412ac442f41Sdrh *pResOut = 0;
413ac442f41Sdrh return SQLITE_OK;
414ac442f41Sdrh }
41514714167Sdrh #endif
416ac442f41Sdrh
4172f4d0ec3Sdrh
418ac442f41Sdrh /*
419ac442f41Sdrh ** File control method. For custom operations on an memdb-file.
420ac442f41Sdrh */
memdbFileControl(sqlite3_file * pFile,int op,void * pArg)421ac442f41Sdrh static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
4222f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
423ac442f41Sdrh int rc = SQLITE_NOTFOUND;
4242f4d0ec3Sdrh memdbEnter(p);
425ac442f41Sdrh if( op==SQLITE_FCNTL_VFSNAME ){
426ac442f41Sdrh *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
427ac442f41Sdrh rc = SQLITE_OK;
428ac442f41Sdrh }
4296ca64481Sdrh if( op==SQLITE_FCNTL_SIZE_LIMIT ){
4306ca64481Sdrh sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
4316ca64481Sdrh if( iLimit<p->sz ){
4326ca64481Sdrh if( iLimit<0 ){
4336ca64481Sdrh iLimit = p->szMax;
4346ca64481Sdrh }else{
4356ca64481Sdrh iLimit = p->sz;
4366ca64481Sdrh }
4376ca64481Sdrh }
4386ca64481Sdrh p->szMax = iLimit;
4396ca64481Sdrh *(sqlite3_int64*)pArg = iLimit;
4406ca64481Sdrh rc = SQLITE_OK;
4416ca64481Sdrh }
4422f4d0ec3Sdrh memdbLeave(p);
443ac442f41Sdrh return rc;
444ac442f41Sdrh }
445ac442f41Sdrh
4465f9d192dSdrh #if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
447ac442f41Sdrh /*
448ac442f41Sdrh ** Return the sector-size in bytes for an memdb-file.
449ac442f41Sdrh */
450ac442f41Sdrh static int memdbSectorSize(sqlite3_file *pFile){
451ac442f41Sdrh return 1024;
452ac442f41Sdrh }
4535f9d192dSdrh #endif
454ac442f41Sdrh
455ac442f41Sdrh /*
456ac442f41Sdrh ** Return the device characteristic flags supported by an memdb-file.
457ac442f41Sdrh */
memdbDeviceCharacteristics(sqlite3_file * pFile)458ac442f41Sdrh static int memdbDeviceCharacteristics(sqlite3_file *pFile){
459904e48ebSdrh UNUSED_PARAMETER(pFile);
460ac442f41Sdrh return SQLITE_IOCAP_ATOMIC |
461ac442f41Sdrh SQLITE_IOCAP_POWERSAFE_OVERWRITE |
462ac442f41Sdrh SQLITE_IOCAP_SAFE_APPEND |
463ac442f41Sdrh SQLITE_IOCAP_SEQUENTIAL;
464ac442f41Sdrh }
465ac442f41Sdrh
466ac442f41Sdrh /* Fetch a page of a memory-mapped file */
memdbFetch(sqlite3_file * pFile,sqlite3_int64 iOfst,int iAmt,void ** pp)467ac442f41Sdrh static int memdbFetch(
468ac442f41Sdrh sqlite3_file *pFile,
469ac442f41Sdrh sqlite3_int64 iOfst,
470ac442f41Sdrh int iAmt,
471ac442f41Sdrh void **pp
472ac442f41Sdrh ){
4732f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
4742f4d0ec3Sdrh memdbEnter(p);
47588944e6fSdrh if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
47694f0a834Sdrh *pp = 0;
47794f0a834Sdrh }else{
478ac442f41Sdrh p->nMmap++;
479ac442f41Sdrh *pp = (void*)(p->aData + iOfst);
48094f0a834Sdrh }
4812f4d0ec3Sdrh memdbLeave(p);
482ac442f41Sdrh return SQLITE_OK;
483ac442f41Sdrh }
484ac442f41Sdrh
485ac442f41Sdrh /* Release a memory-mapped page */
memdbUnfetch(sqlite3_file * pFile,sqlite3_int64 iOfst,void * pPage)486ac442f41Sdrh static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
4872f4d0ec3Sdrh MemStore *p = ((MemFile*)pFile)->pStore;
488904e48ebSdrh UNUSED_PARAMETER(iOfst);
489904e48ebSdrh UNUSED_PARAMETER(pPage);
4902f4d0ec3Sdrh memdbEnter(p);
491ac442f41Sdrh p->nMmap--;
4922f4d0ec3Sdrh memdbLeave(p);
493ac442f41Sdrh return SQLITE_OK;
494ac442f41Sdrh }
495ac442f41Sdrh
496ac442f41Sdrh /*
497ac442f41Sdrh ** Open an mem file handle.
498ac442f41Sdrh */
memdbOpen(sqlite3_vfs * pVfs,const char * zName,sqlite3_file * pFd,int flags,int * pOutFlags)499ac442f41Sdrh static int memdbOpen(
500ac442f41Sdrh sqlite3_vfs *pVfs,
501ac442f41Sdrh const char *zName,
5022f4d0ec3Sdrh sqlite3_file *pFd,
503ac442f41Sdrh int flags,
504ac442f41Sdrh int *pOutFlags
505ac442f41Sdrh ){
5062f4d0ec3Sdrh MemFile *pFile = (MemFile*)pFd;
5072f4d0ec3Sdrh MemStore *p = 0;
5082f4d0ec3Sdrh int szName;
50990385ddcSdrh UNUSED_PARAMETER(pVfs);
51088944e6fSdrh
5113a9793e4Slarrybr memset(pFile, 0, sizeof(*pFile));
5122f4d0ec3Sdrh szName = sqlite3Strlen30(zName);
5132f4d0ec3Sdrh if( szName>1 && zName[0]=='/' ){
5142f4d0ec3Sdrh int i;
5152d344f94Sdrh #ifndef SQLITE_MUTEX_OMIT
5162f4d0ec3Sdrh sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
5172d344f94Sdrh #endif
5182f4d0ec3Sdrh sqlite3_mutex_enter(pVfsMutex);
5192f4d0ec3Sdrh for(i=0; i<memdb_g.nMemStore; i++){
5202f4d0ec3Sdrh if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
5212f4d0ec3Sdrh p = memdb_g.apMemStore[i];
5222f4d0ec3Sdrh break;
5232f4d0ec3Sdrh }
5242f4d0ec3Sdrh }
5252f4d0ec3Sdrh if( p==0 ){
5262f4d0ec3Sdrh MemStore **apNew;
5272f4d0ec3Sdrh p = sqlite3Malloc( sizeof(*p) + szName + 3 );
5282f4d0ec3Sdrh if( p==0 ){
5292f4d0ec3Sdrh sqlite3_mutex_leave(pVfsMutex);
5302f4d0ec3Sdrh return SQLITE_NOMEM;
5312f4d0ec3Sdrh }
5322f4d0ec3Sdrh apNew = sqlite3Realloc(memdb_g.apMemStore,
5332f4d0ec3Sdrh sizeof(apNew[0])*(memdb_g.nMemStore+1) );
5342f4d0ec3Sdrh if( apNew==0 ){
5352f4d0ec3Sdrh sqlite3_free(p);
5362f4d0ec3Sdrh sqlite3_mutex_leave(pVfsMutex);
5372f4d0ec3Sdrh return SQLITE_NOMEM;
5382f4d0ec3Sdrh }
5392f4d0ec3Sdrh apNew[memdb_g.nMemStore++] = p;
5402f4d0ec3Sdrh memdb_g.apMemStore = apNew;
5412f4d0ec3Sdrh memset(p, 0, sizeof(*p));
5422f4d0ec3Sdrh p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
5432f4d0ec3Sdrh p->szMax = sqlite3GlobalConfig.mxMemdbSize;
5442f4d0ec3Sdrh p->zFName = (char*)&p[1];
5452f4d0ec3Sdrh memcpy(p->zFName, zName, szName+1);
5462f4d0ec3Sdrh p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
5472d344f94Sdrh if( p->pMutex==0 ){
5482d344f94Sdrh memdb_g.nMemStore--;
5492d344f94Sdrh sqlite3_free(p);
5502d344f94Sdrh sqlite3_mutex_leave(pVfsMutex);
5512d344f94Sdrh return SQLITE_NOMEM;
5522d344f94Sdrh }
5532f4d0ec3Sdrh p->nRef = 1;
5542f4d0ec3Sdrh memdbEnter(p);
5552f4d0ec3Sdrh }else{
5562f4d0ec3Sdrh memdbEnter(p);
5572f4d0ec3Sdrh p->nRef++;
5582f4d0ec3Sdrh }
5592f4d0ec3Sdrh sqlite3_mutex_leave(pVfsMutex);
5602f4d0ec3Sdrh }else{
5612f4d0ec3Sdrh p = sqlite3Malloc( sizeof(*p) );
5622f4d0ec3Sdrh if( p==0 ){
5632f4d0ec3Sdrh return SQLITE_NOMEM;
5645f9d192dSdrh }
565ac442f41Sdrh memset(p, 0, sizeof(*p));
5663ec8665eSdrh p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
5672f4d0ec3Sdrh p->szMax = sqlite3GlobalConfig.mxMemdbSize;
5682f4d0ec3Sdrh }
5692f4d0ec3Sdrh pFile->pStore = p;
57088944e6fSdrh if( pOutFlags!=0 ){
57114714167Sdrh *pOutFlags = flags | SQLITE_OPEN_MEMORY;
57288944e6fSdrh }
5732f4d0ec3Sdrh pFd->pMethods = &memdb_io_methods;
5742f4d0ec3Sdrh memdbLeave(p);
575ac442f41Sdrh return SQLITE_OK;
576ac442f41Sdrh }
577ac442f41Sdrh
578067b92baSdrh #if 0 /* Only used to delete rollback journals, super-journals, and WAL
57914714167Sdrh ** files, none of which exist in memdb. So this routine is never used */
580ac442f41Sdrh /*
581ac442f41Sdrh ** Delete the file located at zPath. If the dirSync argument is true,
582ac442f41Sdrh ** ensure the file-system modifications are synced to disk before
583ac442f41Sdrh ** returning.
584ac442f41Sdrh */
585ac442f41Sdrh static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
586ac442f41Sdrh return SQLITE_IOERR_DELETE;
587ac442f41Sdrh }
58814714167Sdrh #endif
589ac442f41Sdrh
590ac442f41Sdrh /*
591ac442f41Sdrh ** Test for access permissions. Return true if the requested permission
592ac442f41Sdrh ** is available, or false otherwise.
59314714167Sdrh **
59414714167Sdrh ** With memdb, no files ever exist on disk. So always return false.
595ac442f41Sdrh */
memdbAccess(sqlite3_vfs * pVfs,const char * zPath,int flags,int * pResOut)596ac442f41Sdrh static int memdbAccess(
597ac442f41Sdrh sqlite3_vfs *pVfs,
598ac442f41Sdrh const char *zPath,
599ac442f41Sdrh int flags,
600ac442f41Sdrh int *pResOut
601ac442f41Sdrh ){
602904e48ebSdrh UNUSED_PARAMETER(pVfs);
603904e48ebSdrh UNUSED_PARAMETER(zPath);
604904e48ebSdrh UNUSED_PARAMETER(flags);
605ac442f41Sdrh *pResOut = 0;
606ac442f41Sdrh return SQLITE_OK;
607ac442f41Sdrh }
608ac442f41Sdrh
609ac442f41Sdrh /*
610ac442f41Sdrh ** Populate buffer zOut with the full canonical pathname corresponding
611ac442f41Sdrh ** to the pathname in zPath. zOut is guaranteed to point to a buffer
612ac442f41Sdrh ** of at least (INST_MAX_PATHNAME+1) bytes.
613ac442f41Sdrh */
memdbFullPathname(sqlite3_vfs * pVfs,const char * zPath,int nOut,char * zOut)614ac442f41Sdrh static int memdbFullPathname(
615ac442f41Sdrh sqlite3_vfs *pVfs,
616ac442f41Sdrh const char *zPath,
617ac442f41Sdrh int nOut,
618ac442f41Sdrh char *zOut
619ac442f41Sdrh ){
620904e48ebSdrh UNUSED_PARAMETER(pVfs);
621ac442f41Sdrh sqlite3_snprintf(nOut, zOut, "%s", zPath);
622ac442f41Sdrh return SQLITE_OK;
623ac442f41Sdrh }
624ac442f41Sdrh
625ac442f41Sdrh /*
626ac442f41Sdrh ** Open the dynamic library located at zPath and return a handle.
627ac442f41Sdrh */
memdbDlOpen(sqlite3_vfs * pVfs,const char * zPath)628ac442f41Sdrh static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
629ac442f41Sdrh return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
630ac442f41Sdrh }
631ac442f41Sdrh
632ac442f41Sdrh /*
633ac442f41Sdrh ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
634ac442f41Sdrh ** utf-8 string describing the most recent error encountered associated
635ac442f41Sdrh ** with dynamic libraries.
636ac442f41Sdrh */
memdbDlError(sqlite3_vfs * pVfs,int nByte,char * zErrMsg)637ac442f41Sdrh static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
638ac442f41Sdrh ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
639ac442f41Sdrh }
640ac442f41Sdrh
641ac442f41Sdrh /*
642ac442f41Sdrh ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
643ac442f41Sdrh */
memdbDlSym(sqlite3_vfs * pVfs,void * p,const char * zSym)644ac442f41Sdrh static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
645ac442f41Sdrh return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
646ac442f41Sdrh }
647ac442f41Sdrh
648ac442f41Sdrh /*
649ac442f41Sdrh ** Close the dynamic library handle pHandle.
650ac442f41Sdrh */
memdbDlClose(sqlite3_vfs * pVfs,void * pHandle)651ac442f41Sdrh static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
652ac442f41Sdrh ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
653ac442f41Sdrh }
654ac442f41Sdrh
655ac442f41Sdrh /*
656ac442f41Sdrh ** Populate the buffer pointed to by zBufOut with nByte bytes of
657ac442f41Sdrh ** random data.
658ac442f41Sdrh */
memdbRandomness(sqlite3_vfs * pVfs,int nByte,char * zBufOut)659ac442f41Sdrh static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
660ac442f41Sdrh return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
661ac442f41Sdrh }
662ac442f41Sdrh
663ac442f41Sdrh /*
664ac442f41Sdrh ** Sleep for nMicro microseconds. Return the number of microseconds
665ac442f41Sdrh ** actually slept.
666ac442f41Sdrh */
memdbSleep(sqlite3_vfs * pVfs,int nMicro)667ac442f41Sdrh static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
668ac442f41Sdrh return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
669ac442f41Sdrh }
670ac442f41Sdrh
67114714167Sdrh #if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
672ac442f41Sdrh /*
673ac442f41Sdrh ** Return the current time as a Julian Day number in *pTimeOut.
674ac442f41Sdrh */
675ac442f41Sdrh static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
676ac442f41Sdrh return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
677ac442f41Sdrh }
67814714167Sdrh #endif
679ac442f41Sdrh
memdbGetLastError(sqlite3_vfs * pVfs,int a,char * b)680ac442f41Sdrh static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
681ac442f41Sdrh return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
682ac442f41Sdrh }
memdbCurrentTimeInt64(sqlite3_vfs * pVfs,sqlite3_int64 * p)683ac442f41Sdrh static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
684ac442f41Sdrh return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
685ac442f41Sdrh }
686ac442f41Sdrh
687ac442f41Sdrh /*
688ac442f41Sdrh ** Translate a database connection pointer and schema name into a
689ac442f41Sdrh ** MemFile pointer.
690ac442f41Sdrh */
memdbFromDbSchema(sqlite3 * db,const char * zSchema)691ac442f41Sdrh static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
692ac442f41Sdrh MemFile *p = 0;
6932f4d0ec3Sdrh MemStore *pStore;
694ac442f41Sdrh int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
695ac442f41Sdrh if( rc ) return 0;
696ac442f41Sdrh if( p->base.pMethods!=&memdb_io_methods ) return 0;
6972f4d0ec3Sdrh pStore = p->pStore;
6982f4d0ec3Sdrh memdbEnter(pStore);
6992f4d0ec3Sdrh if( pStore->zFName!=0 ) p = 0;
7002f4d0ec3Sdrh memdbLeave(pStore);
701ac442f41Sdrh return p;
702ac442f41Sdrh }
703ac442f41Sdrh
704ac442f41Sdrh /*
705cb7d541dSdrh ** Return the serialization of a database
706cb7d541dSdrh */
sqlite3_serialize(sqlite3 * db,const char * zSchema,sqlite3_int64 * piSize,unsigned int mFlags)707cb7d541dSdrh unsigned char *sqlite3_serialize(
708cb7d541dSdrh sqlite3 *db, /* The database connection */
709cb7d541dSdrh const char *zSchema, /* Which database within the connection */
710cb7d541dSdrh sqlite3_int64 *piSize, /* Write size here, if not NULL */
711cb7d541dSdrh unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
712cb7d541dSdrh ){
713b2194ceaSdrh MemFile *p;
714b2194ceaSdrh int iDb;
715cb7d541dSdrh Btree *pBt;
716cb7d541dSdrh sqlite3_int64 sz;
717cb7d541dSdrh int szPage = 0;
718cb7d541dSdrh sqlite3_stmt *pStmt = 0;
719cb7d541dSdrh unsigned char *pOut;
720cb7d541dSdrh char *zSql;
721cb7d541dSdrh int rc;
722cb7d541dSdrh
7236630f940Smistachkin #ifdef SQLITE_ENABLE_API_ARMOR
7246630f940Smistachkin if( !sqlite3SafetyCheckOk(db) ){
7256630f940Smistachkin (void)SQLITE_MISUSE_BKPT;
7266630f940Smistachkin return 0;
7276630f940Smistachkin }
7286630f940Smistachkin #endif
7296630f940Smistachkin
730b2194ceaSdrh if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
731b2194ceaSdrh p = memdbFromDbSchema(db, zSchema);
732b2194ceaSdrh iDb = sqlite3FindDbName(db, zSchema);
733cb7d541dSdrh if( piSize ) *piSize = -1;
734cb7d541dSdrh if( iDb<0 ) return 0;
735cb7d541dSdrh if( p ){
7362f4d0ec3Sdrh MemStore *pStore = p->pStore;
7372f4d0ec3Sdrh assert( pStore->pMutex==0 );
7382f4d0ec3Sdrh if( piSize ) *piSize = pStore->sz;
739cb7d541dSdrh if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
7402f4d0ec3Sdrh pOut = pStore->aData;
741cb7d541dSdrh }else{
7422f4d0ec3Sdrh pOut = sqlite3_malloc64( pStore->sz );
7432f4d0ec3Sdrh if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
744cb7d541dSdrh }
745cb7d541dSdrh return pOut;
746cb7d541dSdrh }
747cb7d541dSdrh pBt = db->aDb[iDb].pBt;
748cb7d541dSdrh if( pBt==0 ) return 0;
749cb7d541dSdrh szPage = sqlite3BtreeGetPageSize(pBt);
750cb7d541dSdrh zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
751cb7d541dSdrh rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
752cb7d541dSdrh sqlite3_free(zSql);
753cb7d541dSdrh if( rc ) return 0;
7548784efaeSdrh rc = sqlite3_step(pStmt);
7558784efaeSdrh if( rc!=SQLITE_ROW ){
7568784efaeSdrh pOut = 0;
7578784efaeSdrh }else{
758cb7d541dSdrh sz = sqlite3_column_int64(pStmt, 0)*szPage;
759cb7d541dSdrh if( piSize ) *piSize = sz;
760cb7d541dSdrh if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
761cb7d541dSdrh pOut = 0;
762cb7d541dSdrh }else{
763cb7d541dSdrh pOut = sqlite3_malloc64( sz );
764cb7d541dSdrh if( pOut ){
765cb7d541dSdrh int nPage = sqlite3_column_int(pStmt, 0);
766cb7d541dSdrh Pager *pPager = sqlite3BtreePager(pBt);
767cb7d541dSdrh int pgno;
768cb7d541dSdrh for(pgno=1; pgno<=nPage; pgno++){
769cb7d541dSdrh DbPage *pPage = 0;
770cb7d541dSdrh unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
771cb7d541dSdrh rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
772cb7d541dSdrh if( rc==SQLITE_OK ){
773cb7d541dSdrh memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
774cb7d541dSdrh }else{
775cb7d541dSdrh memset(pTo, 0, szPage);
776cb7d541dSdrh }
777cb7d541dSdrh sqlite3PagerUnref(pPage);
778cb7d541dSdrh }
779cb7d541dSdrh }
780cb7d541dSdrh }
7818784efaeSdrh }
782cb7d541dSdrh sqlite3_finalize(pStmt);
783cb7d541dSdrh return pOut;
784cb7d541dSdrh }
785cb7d541dSdrh
7863ec8665eSdrh /* Convert zSchema to a MemDB and initialize its content.
7873ec8665eSdrh */
sqlite3_deserialize(sqlite3 * db,const char * zSchema,unsigned char * pData,sqlite3_int64 szDb,sqlite3_int64 szBuf,unsigned mFlags)7883ec8665eSdrh int sqlite3_deserialize(
7893ec8665eSdrh sqlite3 *db, /* The database connection */
7903ec8665eSdrh const char *zSchema, /* Which DB to reopen with the deserialization */
7913ec8665eSdrh unsigned char *pData, /* The serialized database content */
7923ec8665eSdrh sqlite3_int64 szDb, /* Number bytes in the deserialization */
7933ec8665eSdrh sqlite3_int64 szBuf, /* Total size of buffer pData[] */
7943ec8665eSdrh unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
7953ec8665eSdrh ){
7963ec8665eSdrh MemFile *p;
7973ec8665eSdrh char *zSql;
7983ec8665eSdrh sqlite3_stmt *pStmt = 0;
7993ec8665eSdrh int rc;
8003ec8665eSdrh int iDb;
8013ec8665eSdrh
8026630f940Smistachkin #ifdef SQLITE_ENABLE_API_ARMOR
8036630f940Smistachkin if( !sqlite3SafetyCheckOk(db) ){
8046630f940Smistachkin return SQLITE_MISUSE_BKPT;
8056630f940Smistachkin }
8066630f940Smistachkin if( szDb<0 ) return SQLITE_MISUSE_BKPT;
8076630f940Smistachkin if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
8086630f940Smistachkin #endif
8096630f940Smistachkin
8103ec8665eSdrh sqlite3_mutex_enter(db->mutex);
8113ec8665eSdrh if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
8123ec8665eSdrh iDb = sqlite3FindDbName(db, zSchema);
81353fa0250Sdrh testcase( iDb==1 );
81453fa0250Sdrh if( iDb<2 && iDb!=0 ){
8153ec8665eSdrh rc = SQLITE_ERROR;
8163ec8665eSdrh goto end_deserialize;
8173ec8665eSdrh }
8183ec8665eSdrh zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
819672f07c6Sdrh if( zSql==0 ){
820672f07c6Sdrh rc = SQLITE_NOMEM;
821672f07c6Sdrh }else{
8223ec8665eSdrh rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
8233ec8665eSdrh sqlite3_free(zSql);
824672f07c6Sdrh }
8253ec8665eSdrh if( rc ) goto end_deserialize;
8263ec8665eSdrh db->init.iDb = (u8)iDb;
8273ec8665eSdrh db->init.reopenMemdb = 1;
8283ec8665eSdrh rc = sqlite3_step(pStmt);
8293ec8665eSdrh db->init.reopenMemdb = 0;
8303ec8665eSdrh if( rc!=SQLITE_DONE ){
8313ec8665eSdrh rc = SQLITE_ERROR;
8323ec8665eSdrh goto end_deserialize;
8333ec8665eSdrh }
8343ec8665eSdrh p = memdbFromDbSchema(db, zSchema);
8358784efaeSdrh if( p==0 ){
8368784efaeSdrh rc = SQLITE_ERROR;
8378784efaeSdrh }else{
8382f4d0ec3Sdrh MemStore *pStore = p->pStore;
8392f4d0ec3Sdrh pStore->aData = pData;
840ff01ee34Sdrh pData = 0;
8412f4d0ec3Sdrh pStore->sz = szDb;
8422f4d0ec3Sdrh pStore->szAlloc = szBuf;
8432f4d0ec3Sdrh pStore->szMax = szBuf;
8442f4d0ec3Sdrh if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
8452f4d0ec3Sdrh pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
8466ca64481Sdrh }
8472f4d0ec3Sdrh pStore->mFlags = mFlags;
8483ec8665eSdrh rc = SQLITE_OK;
8498784efaeSdrh }
8508784efaeSdrh
8513ec8665eSdrh end_deserialize:
8523ec8665eSdrh sqlite3_finalize(pStmt);
853ff01ee34Sdrh if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
854ff01ee34Sdrh sqlite3_free(pData);
855ff01ee34Sdrh }
8563ec8665eSdrh sqlite3_mutex_leave(db->mutex);
8573ec8665eSdrh return rc;
8583ec8665eSdrh }
8593ec8665eSdrh
860cb7d541dSdrh /*
861ac442f41Sdrh ** This routine is called when the extension is loaded.
862ac442f41Sdrh ** Register the new VFS.
863ac442f41Sdrh */
sqlite3MemdbInit(void)864ac442f41Sdrh int sqlite3MemdbInit(void){
8655f9d192dSdrh sqlite3_vfs *pLower = sqlite3_vfs_find(0);
866a959bf53Sdrh unsigned int sz;
867a959bf53Sdrh if( NEVER(pLower==0) ) return SQLITE_ERROR;
868a959bf53Sdrh sz = pLower->szOsFile;
8695f9d192dSdrh memdb_vfs.pAppData = pLower;
870f25f8d58Sdrh /* The following conditional can only be true when compiled for
871f25f8d58Sdrh ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
872f25f8d58Sdrh ** it in, to be safe, but it is marked as NO_TEST since there
873f25f8d58Sdrh ** is no way to reach it under most builds. */
874f25f8d58Sdrh if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
8755f9d192dSdrh memdb_vfs.szOsFile = sz;
876ac442f41Sdrh return sqlite3_vfs_register(&memdb_vfs, 0);
877ac442f41Sdrh }
8788d889afcSdrh #endif /* SQLITE_OMIT_DESERIALIZE */
879