blob: 68bec75ea91ba388cf189fcc458991d3cf0a7be0 [file] [log] [blame]
drhac442f42018-01-03 01:28:46 +00001/*
2** 2016-09-07
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11******************************************************************************
12**
drh99abe5c2018-01-03 22:48:38 +000013** This file implements in-memory VFS. A database is held as a contiguous
14** block of memory.
15**
16** This file also implements interface sqlite3_serialize() and
17** sqlite3_deserialize().
drhac442f42018-01-03 01:28:46 +000018*/
drh9c6396e2018-03-06 21:43:19 +000019#ifdef SQLITE_ENABLE_DESERIALIZE
drhac442f42018-01-03 01:28:46 +000020#include "sqliteInt.h"
21
22/*
23** Forward declaration of objects used by this utility
24*/
25typedef struct sqlite3_vfs MemVfs;
26typedef struct MemFile MemFile;
27
28/* Access to a lower-level VFS that (might) implement dynamic loading,
29** access to randomness, etc.
30*/
31#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
32
33/* An open file */
34struct MemFile {
35 sqlite3_file base; /* IO methods */
36 sqlite3_int64 sz; /* Size of the file */
37 sqlite3_int64 szMax; /* Space allocated to aData */
38 unsigned char *aData; /* content of the file */
39 int nMmap; /* Number of memory mapped pages */
40 unsigned mFlags; /* Flags */
41 int eLock; /* Most recent lock against this file */
42};
43
44/*
45** Methods for MemFile
46*/
47static int memdbClose(sqlite3_file*);
48static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
49static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
50static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
51static int memdbSync(sqlite3_file*, int flags);
52static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
53static int memdbLock(sqlite3_file*, int);
drh14714162018-03-06 19:14:32 +000054/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
drhac442f42018-01-03 01:28:46 +000055static int memdbFileControl(sqlite3_file*, int op, void *pArg);
drh5f9d1922018-03-06 04:01:08 +000056/* static int memdbSectorSize(sqlite3_file*); // not used */
drhac442f42018-01-03 01:28:46 +000057static int memdbDeviceCharacteristics(sqlite3_file*);
drhac442f42018-01-03 01:28:46 +000058static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
59static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
60
61/*
62** Methods for MemVfs
63*/
64static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
drh14714162018-03-06 19:14:32 +000065/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
drhac442f42018-01-03 01:28:46 +000066static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
67static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
68static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
69static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
70static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
71static void memdbDlClose(sqlite3_vfs*, void*);
72static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
73static int memdbSleep(sqlite3_vfs*, int microseconds);
drh14714162018-03-06 19:14:32 +000074/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
drhac442f42018-01-03 01:28:46 +000075static int memdbGetLastError(sqlite3_vfs*, int, char *);
76static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
77
78static sqlite3_vfs memdb_vfs = {
79 2, /* iVersion */
80 0, /* szOsFile (set when registered) */
81 1024, /* mxPathname */
82 0, /* pNext */
83 "memdb", /* zName */
84 0, /* pAppData (set when registered) */
85 memdbOpen, /* xOpen */
drh14714162018-03-06 19:14:32 +000086 0, /* memdbDelete, */ /* xDelete */
drhac442f42018-01-03 01:28:46 +000087 memdbAccess, /* xAccess */
88 memdbFullPathname, /* xFullPathname */
89 memdbDlOpen, /* xDlOpen */
90 memdbDlError, /* xDlError */
91 memdbDlSym, /* xDlSym */
92 memdbDlClose, /* xDlClose */
93 memdbRandomness, /* xRandomness */
94 memdbSleep, /* xSleep */
drh14714162018-03-06 19:14:32 +000095 0, /* memdbCurrentTime, */ /* xCurrentTime */
drhac442f42018-01-03 01:28:46 +000096 memdbGetLastError, /* xGetLastError */
97 memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
98};
99
100static const sqlite3_io_methods memdb_io_methods = {
101 3, /* iVersion */
102 memdbClose, /* xClose */
103 memdbRead, /* xRead */
104 memdbWrite, /* xWrite */
105 memdbTruncate, /* xTruncate */
106 memdbSync, /* xSync */
107 memdbFileSize, /* xFileSize */
108 memdbLock, /* xLock */
109 memdbLock, /* xUnlock - same as xLock in this case */
drh14714162018-03-06 19:14:32 +0000110 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
drhac442f42018-01-03 01:28:46 +0000111 memdbFileControl, /* xFileControl */
drh5f9d1922018-03-06 04:01:08 +0000112 0, /* memdbSectorSize,*/ /* xSectorSize */
drhac442f42018-01-03 01:28:46 +0000113 memdbDeviceCharacteristics, /* xDeviceCharacteristics */
drh99abe5c2018-01-03 22:48:38 +0000114 0, /* xShmMap */
115 0, /* xShmLock */
116 0, /* xShmBarrier */
117 0, /* xShmUnmap */
drhac442f42018-01-03 01:28:46 +0000118 memdbFetch, /* xFetch */
119 memdbUnfetch /* xUnfetch */
120};
121
122
123
124/*
125** Close an memdb-file.
126**
127** The pData pointer is owned by the application, so there is nothing
128** to free.
129*/
130static int memdbClose(sqlite3_file *pFile){
131 MemFile *p = (MemFile *)pFile;
drh3ec86652018-01-03 19:03:31 +0000132 if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
drhac442f42018-01-03 01:28:46 +0000133 return SQLITE_OK;
134}
135
136/*
137** Read data from an memdb-file.
138*/
139static int memdbRead(
140 sqlite3_file *pFile,
141 void *zBuf,
142 int iAmt,
143 sqlite_int64 iOfst
144){
145 MemFile *p = (MemFile *)pFile;
146 if( iOfst+iAmt>p->sz ){
147 memset(zBuf, 0, iAmt);
drhcb7d5412018-01-03 16:49:52 +0000148 if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
drhac442f42018-01-03 01:28:46 +0000149 return SQLITE_IOERR_SHORT_READ;
150 }
151 memcpy(zBuf, p->aData+iOfst, iAmt);
152 return SQLITE_OK;
153}
154
155/*
156** Try to enlarge the memory allocation to hold at least sz bytes
157*/
158static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
159 unsigned char *pNew;
drh5f9d1922018-03-06 04:01:08 +0000160 if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
161 return SQLITE_FULL;
162 }
drhac442f42018-01-03 01:28:46 +0000163 pNew = sqlite3_realloc64(p->aData, newSz);
drh5f9d1922018-03-06 04:01:08 +0000164 if( pNew==0 ) return SQLITE_NOMEM;
drhac442f42018-01-03 01:28:46 +0000165 p->aData = pNew;
166 p->szMax = newSz;
167 return SQLITE_OK;
168}
169
170/*
171** Write data to an memdb-file.
172*/
173static int memdbWrite(
174 sqlite3_file *pFile,
175 const void *z,
176 int iAmt,
177 sqlite_int64 iOfst
178){
179 MemFile *p = (MemFile *)pFile;
180 if( iOfst+iAmt>p->sz ){
drh5f9d1922018-03-06 04:01:08 +0000181 int rc;
182 if( iOfst+iAmt>p->szMax
183 && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
184 ){
185 return rc;
drhac442f42018-01-03 01:28:46 +0000186 }
187 if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
188 p->sz = iOfst+iAmt;
189 }
190 memcpy(p->aData+iOfst, z, iAmt);
191 return SQLITE_OK;
192}
193
194/*
195** Truncate an memdb-file.
drh14714162018-03-06 19:14:32 +0000196**
197** In rollback mode (which is always the case for memdb, as it does not
198** support WAL mode) the truncate() method is only used to reduce
199** the size of a file, never to increase the size.
drhac442f42018-01-03 01:28:46 +0000200*/
201static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
202 MemFile *p = (MemFile *)pFile;
drh14714162018-03-06 19:14:32 +0000203 if( NEVER(size>p->sz) ) return SQLITE_FULL;
drhac442f42018-01-03 01:28:46 +0000204 p->sz = size;
205 return SQLITE_OK;
206}
207
208/*
209** Sync an memdb-file.
210*/
211static int memdbSync(sqlite3_file *pFile, int flags){
212 return SQLITE_OK;
213}
214
215/*
216** Return the current file-size of an memdb-file.
217*/
218static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
219 MemFile *p = (MemFile *)pFile;
220 *pSize = p->sz;
221 return SQLITE_OK;
222}
223
224/*
225** Lock an memdb-file.
226*/
227static int memdbLock(sqlite3_file *pFile, int eLock){
228 MemFile *p = (MemFile *)pFile;
229 p->eLock = eLock;
230 return SQLITE_OK;
231}
232
drh14714162018-03-06 19:14:32 +0000233#if 0 /* Never used because memdbAccess() always returns false */
drhac442f42018-01-03 01:28:46 +0000234/*
235** Check if another file-handle holds a RESERVED lock on an memdb-file.
236*/
237static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
238 *pResOut = 0;
239 return SQLITE_OK;
240}
drh14714162018-03-06 19:14:32 +0000241#endif
drhac442f42018-01-03 01:28:46 +0000242
243/*
244** File control method. For custom operations on an memdb-file.
245*/
246static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
247 MemFile *p = (MemFile *)pFile;
248 int rc = SQLITE_NOTFOUND;
249 if( op==SQLITE_FCNTL_VFSNAME ){
250 *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
251 rc = SQLITE_OK;
252 }
253 return rc;
254}
255
drh5f9d1922018-03-06 04:01:08 +0000256#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
drhac442f42018-01-03 01:28:46 +0000257/*
258** Return the sector-size in bytes for an memdb-file.
259*/
260static int memdbSectorSize(sqlite3_file *pFile){
261 return 1024;
262}
drh5f9d1922018-03-06 04:01:08 +0000263#endif
drhac442f42018-01-03 01:28:46 +0000264
265/*
266** Return the device characteristic flags supported by an memdb-file.
267*/
268static int memdbDeviceCharacteristics(sqlite3_file *pFile){
269 return SQLITE_IOCAP_ATOMIC |
270 SQLITE_IOCAP_POWERSAFE_OVERWRITE |
271 SQLITE_IOCAP_SAFE_APPEND |
272 SQLITE_IOCAP_SEQUENTIAL;
273}
274
drhac442f42018-01-03 01:28:46 +0000275/* Fetch a page of a memory-mapped file */
276static int memdbFetch(
277 sqlite3_file *pFile,
278 sqlite3_int64 iOfst,
279 int iAmt,
280 void **pp
281){
282 MemFile *p = (MemFile *)pFile;
283 p->nMmap++;
284 *pp = (void*)(p->aData + iOfst);
285 return SQLITE_OK;
286}
287
288/* Release a memory-mapped page */
289static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
290 MemFile *p = (MemFile *)pFile;
291 p->nMmap--;
292 return SQLITE_OK;
293}
294
295/*
296** Open an mem file handle.
297*/
298static int memdbOpen(
299 sqlite3_vfs *pVfs,
300 const char *zName,
301 sqlite3_file *pFile,
302 int flags,
303 int *pOutFlags
304){
305 MemFile *p = (MemFile*)pFile;
drh5f9d1922018-03-06 04:01:08 +0000306 if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
307 return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
308 }
drhac442f42018-01-03 01:28:46 +0000309 memset(p, 0, sizeof(*p));
drh3ec86652018-01-03 19:03:31 +0000310 p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
drh14714162018-03-06 19:14:32 +0000311 assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
312 *pOutFlags = flags | SQLITE_OPEN_MEMORY;
drhac442f42018-01-03 01:28:46 +0000313 p->base.pMethods = &memdb_io_methods;
314 return SQLITE_OK;
315}
316
drh14714162018-03-06 19:14:32 +0000317#if 0 /* Only used to delete rollback journals, master journals, and WAL
318 ** files, none of which exist in memdb. So this routine is never used */
drhac442f42018-01-03 01:28:46 +0000319/*
320** Delete the file located at zPath. If the dirSync argument is true,
321** ensure the file-system modifications are synced to disk before
322** returning.
323*/
324static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
325 return SQLITE_IOERR_DELETE;
326}
drh14714162018-03-06 19:14:32 +0000327#endif
drhac442f42018-01-03 01:28:46 +0000328
329/*
330** Test for access permissions. Return true if the requested permission
331** is available, or false otherwise.
drh14714162018-03-06 19:14:32 +0000332**
333** With memdb, no files ever exist on disk. So always return false.
drhac442f42018-01-03 01:28:46 +0000334*/
335static int memdbAccess(
336 sqlite3_vfs *pVfs,
337 const char *zPath,
338 int flags,
339 int *pResOut
340){
341 *pResOut = 0;
342 return SQLITE_OK;
343}
344
345/*
346** Populate buffer zOut with the full canonical pathname corresponding
347** to the pathname in zPath. zOut is guaranteed to point to a buffer
348** of at least (INST_MAX_PATHNAME+1) bytes.
349*/
350static int memdbFullPathname(
351 sqlite3_vfs *pVfs,
352 const char *zPath,
353 int nOut,
354 char *zOut
355){
356 sqlite3_snprintf(nOut, zOut, "%s", zPath);
357 return SQLITE_OK;
358}
359
360/*
361** Open the dynamic library located at zPath and return a handle.
362*/
363static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
364 return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
365}
366
367/*
368** Populate the buffer zErrMsg (size nByte bytes) with a human readable
369** utf-8 string describing the most recent error encountered associated
370** with dynamic libraries.
371*/
372static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
373 ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
374}
375
376/*
377** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
378*/
379static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
380 return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
381}
382
383/*
384** Close the dynamic library handle pHandle.
385*/
386static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
387 ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
388}
389
390/*
391** Populate the buffer pointed to by zBufOut with nByte bytes of
392** random data.
393*/
394static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
395 return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
396}
397
398/*
399** Sleep for nMicro microseconds. Return the number of microseconds
400** actually slept.
401*/
402static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
403 return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
404}
405
drh14714162018-03-06 19:14:32 +0000406#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
drhac442f42018-01-03 01:28:46 +0000407/*
408** Return the current time as a Julian Day number in *pTimeOut.
409*/
410static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
411 return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
412}
drh14714162018-03-06 19:14:32 +0000413#endif
drhac442f42018-01-03 01:28:46 +0000414
415static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
416 return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
417}
418static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
419 return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
420}
421
422/*
423** Translate a database connection pointer and schema name into a
424** MemFile pointer.
425*/
426static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
427 MemFile *p = 0;
428 int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
429 if( rc ) return 0;
430 if( p->base.pMethods!=&memdb_io_methods ) return 0;
431 return p;
432}
433
434/*
drhcb7d5412018-01-03 16:49:52 +0000435** Return the serialization of a database
436*/
437unsigned char *sqlite3_serialize(
438 sqlite3 *db, /* The database connection */
439 const char *zSchema, /* Which database within the connection */
440 sqlite3_int64 *piSize, /* Write size here, if not NULL */
441 unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
442){
drhb2194ce2018-03-01 22:18:26 +0000443 MemFile *p;
444 int iDb;
drhcb7d5412018-01-03 16:49:52 +0000445 Btree *pBt;
446 sqlite3_int64 sz;
447 int szPage = 0;
448 sqlite3_stmt *pStmt = 0;
449 unsigned char *pOut;
450 char *zSql;
451 int rc;
452
mistachkin6630f942018-03-08 19:56:52 +0000453#ifdef SQLITE_ENABLE_API_ARMOR
454 if( !sqlite3SafetyCheckOk(db) ){
455 (void)SQLITE_MISUSE_BKPT;
456 return 0;
457 }
458#endif
459
drhb2194ce2018-03-01 22:18:26 +0000460 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
461 p = memdbFromDbSchema(db, zSchema);
462 iDb = sqlite3FindDbName(db, zSchema);
drhcb7d5412018-01-03 16:49:52 +0000463 if( piSize ) *piSize = -1;
464 if( iDb<0 ) return 0;
465 if( p ){
466 if( piSize ) *piSize = p->sz;
467 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
468 pOut = p->aData;
469 }else{
470 pOut = sqlite3_malloc64( p->sz );
471 if( pOut ) memcpy(pOut, p->aData, p->sz);
472 }
473 return pOut;
474 }
475 pBt = db->aDb[iDb].pBt;
476 if( pBt==0 ) return 0;
477 szPage = sqlite3BtreeGetPageSize(pBt);
478 zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
479 rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
480 sqlite3_free(zSql);
481 if( rc ) return 0;
drh8784efa2018-03-06 20:54:27 +0000482 rc = sqlite3_step(pStmt);
483 if( rc!=SQLITE_ROW ){
drhcb7d5412018-01-03 16:49:52 +0000484 pOut = 0;
485 }else{
drh8784efa2018-03-06 20:54:27 +0000486 sz = sqlite3_column_int64(pStmt, 0)*szPage;
487 if( piSize ) *piSize = sz;
488 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
489 pOut = 0;
490 }else{
491 pOut = sqlite3_malloc64( sz );
492 if( pOut ){
493 int nPage = sqlite3_column_int(pStmt, 0);
494 Pager *pPager = sqlite3BtreePager(pBt);
495 int pgno;
496 for(pgno=1; pgno<=nPage; pgno++){
497 DbPage *pPage = 0;
498 unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
499 rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
500 if( rc==SQLITE_OK ){
501 memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
502 }else{
503 memset(pTo, 0, szPage);
504 }
505 sqlite3PagerUnref(pPage);
drhcb7d5412018-01-03 16:49:52 +0000506 }
drhcb7d5412018-01-03 16:49:52 +0000507 }
508 }
509 }
510 sqlite3_finalize(pStmt);
511 return pOut;
512}
513
drh3ec86652018-01-03 19:03:31 +0000514/* Convert zSchema to a MemDB and initialize its content.
515*/
516int sqlite3_deserialize(
517 sqlite3 *db, /* The database connection */
518 const char *zSchema, /* Which DB to reopen with the deserialization */
519 unsigned char *pData, /* The serialized database content */
520 sqlite3_int64 szDb, /* Number bytes in the deserialization */
521 sqlite3_int64 szBuf, /* Total size of buffer pData[] */
522 unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
523){
524 MemFile *p;
525 char *zSql;
526 sqlite3_stmt *pStmt = 0;
527 int rc;
528 int iDb;
529
mistachkin6630f942018-03-08 19:56:52 +0000530#ifdef SQLITE_ENABLE_API_ARMOR
531 if( !sqlite3SafetyCheckOk(db) ){
532 return SQLITE_MISUSE_BKPT;
533 }
534 if( szDb<0 ) return SQLITE_MISUSE_BKPT;
535 if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
536#endif
537
drh3ec86652018-01-03 19:03:31 +0000538 sqlite3_mutex_enter(db->mutex);
539 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
540 iDb = sqlite3FindDbName(db, zSchema);
541 if( iDb<0 ){
542 rc = SQLITE_ERROR;
543 goto end_deserialize;
544 }
545 zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
546 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
547 sqlite3_free(zSql);
548 if( rc ) goto end_deserialize;
549 db->init.iDb = (u8)iDb;
550 db->init.reopenMemdb = 1;
551 rc = sqlite3_step(pStmt);
552 db->init.reopenMemdb = 0;
553 if( rc!=SQLITE_DONE ){
554 rc = SQLITE_ERROR;
555 goto end_deserialize;
556 }
557 p = memdbFromDbSchema(db, zSchema);
drh8784efa2018-03-06 20:54:27 +0000558 if( p==0 ){
559 rc = SQLITE_ERROR;
560 }else{
561 p->aData = pData;
562 p->sz = szDb;
563 p->szMax = szBuf;
564 p->mFlags = mFlags;
565 rc = SQLITE_OK;
566 }
567
drh3ec86652018-01-03 19:03:31 +0000568end_deserialize:
569 sqlite3_finalize(pStmt);
570 sqlite3_mutex_leave(db->mutex);
571 return rc;
572}
573
drhac442f42018-01-03 01:28:46 +0000574/*
575** This routine is called when the extension is loaded.
576** Register the new VFS.
577*/
578int sqlite3MemdbInit(void){
drh5f9d1922018-03-06 04:01:08 +0000579 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
580 int sz = pLower->szOsFile;
581 memdb_vfs.pAppData = pLower;
drh4811a712018-03-07 01:37:05 +0000582 /* In all known configurations of SQLite, the size of a default
583 ** sqlite3_file is greater than the size of a memdb sqlite3_file.
584 ** Should that ever change, remove the following NEVER() */
585 if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
drh5f9d1922018-03-06 04:01:08 +0000586 memdb_vfs.szOsFile = sz;
drhac442f42018-01-03 01:28:46 +0000587 return sqlite3_vfs_register(&memdb_vfs, 0);
588}
drh9c6396e2018-03-06 21:43:19 +0000589#endif /* SQLITE_ENABLE_DESERIALIZE */