blob: 31b2324b93f12e4677cc4c9d68afe61732f27592 [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**
drh840fda42018-03-28 15:06:39 +000013** This file implements an in-memory VFS. A database is held as a contiguous
drh99abe5c2018-01-03 22:48:38 +000014** block of memory.
15**
16** This file also implements interface sqlite3_serialize() and
17** sqlite3_deserialize().
drhac442f42018-01-03 01:28:46 +000018*/
drhac442f42018-01-03 01:28:46 +000019#include "sqliteInt.h"
drh8d889af2021-05-08 17:18:23 +000020#ifndef SQLITE_OMIT_DESERIALIZE
drhac442f42018-01-03 01:28:46 +000021
22/*
23** Forward declaration of objects used by this utility
24*/
25typedef struct sqlite3_vfs MemVfs;
26typedef struct MemFile MemFile;
drh2f4d0ec2021-05-10 23:48:46 +000027typedef struct MemStore MemStore;
drhac442f42018-01-03 01:28:46 +000028
29/* Access to a lower-level VFS that (might) implement dynamic loading,
30** access to randomness, etc.
31*/
32#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
33
drh2f4d0ec2021-05-10 23:48:46 +000034/* Storage for a memdb file.
35**
36** An memdb object can be shared or separate. Shared memdb objects can be
37** used by more than one database connection. Mutexes are used by shared
38** memdb objects to coordinate access. Separate memdb objects are only
39** connected to a single database connection and do not require additional
40** mutexes.
41**
42** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
43** using "file:/name?vfs=memdb". The first character of the name must be
44** "/" or else the object will be a separate memdb object. All shared
45** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
46**
47** Separate memdb objects are created using a name that does not begin
48** with "/" or using sqlite3_deserialize().
49**
50** Access rules for shared MemStore objects:
51**
52** * .zFName is initialized when the object is created and afterwards
53** is unchanged until the object is destroyed. So it can be accessed
54** at any time as long as we know the object is not being destroyed,
55** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
56** .pMutex is held or the object is not part of memdb_g.apMemStore[].
57**
58** * Can .pMutex can only be changed while holding the
59** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
60** of memdb_g.apMemStore[].
61**
62** * Other fields can only be changed while holding the .pMutex mutex
63** or when the .nRef is less than zero and the object is not part of
64** memdb_g.apMemStore[].
65**
66** * The .aData pointer has the added requirement that it can can only
67** be changed (for resizing) when nMmap is zero.
68**
69*/
70struct MemStore {
drhac442f42018-01-03 01:28:46 +000071 sqlite3_int64 sz; /* Size of the file */
drh6ca64482019-01-22 16:06:20 +000072 sqlite3_int64 szAlloc; /* Space allocated to aData */
73 sqlite3_int64 szMax; /* Maximum allowed size of the file */
drhac442f42018-01-03 01:28:46 +000074 unsigned char *aData; /* content of the file */
drh2f4d0ec2021-05-10 23:48:46 +000075 sqlite3_mutex *pMutex; /* Used by shared stores only */
drhac442f42018-01-03 01:28:46 +000076 int nMmap; /* Number of memory mapped pages */
77 unsigned mFlags; /* Flags */
drh2f4d0ec2021-05-10 23:48:46 +000078 int nRdLock; /* Number of readers */
79 int nWrLock; /* Number of writers. (Always 0 or 1) */
80 int nRef; /* Number of users of this MemStore */
81 char *zFName; /* The filename for shared stores */
82};
83
84/* An open file */
85struct MemFile {
86 sqlite3_file base; /* IO methods */
87 MemStore *pStore; /* The storage */
drhac442f42018-01-03 01:28:46 +000088 int eLock; /* Most recent lock against this file */
89};
90
91/*
larrybr99bd5522021-05-19 02:33:42 +000092** File-scope variables for holding the memdb files that are accessible
drh2f4d0ec2021-05-10 23:48:46 +000093** to multiple database connections in separate threads.
94**
95** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
96*/
larrybr99bd5522021-05-19 02:33:42 +000097static struct MemFS {
drh2f4d0ec2021-05-10 23:48:46 +000098 int nMemStore; /* Number of shared MemStore objects */
99 MemStore **apMemStore; /* Array of all shared MemStore objects */
100} memdb_g;
101
102/*
drhac442f42018-01-03 01:28:46 +0000103** Methods for MemFile
104*/
105static int memdbClose(sqlite3_file*);
106static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
107static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
108static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
109static int memdbSync(sqlite3_file*, int flags);
110static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
111static int memdbLock(sqlite3_file*, int);
drh14714162018-03-06 19:14:32 +0000112/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
drhac442f42018-01-03 01:28:46 +0000113static int memdbFileControl(sqlite3_file*, int op, void *pArg);
drh5f9d1922018-03-06 04:01:08 +0000114/* static int memdbSectorSize(sqlite3_file*); // not used */
drhac442f42018-01-03 01:28:46 +0000115static int memdbDeviceCharacteristics(sqlite3_file*);
drhac442f42018-01-03 01:28:46 +0000116static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
117static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
118
119/*
120** Methods for MemVfs
121*/
122static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
drh14714162018-03-06 19:14:32 +0000123/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
drhac442f42018-01-03 01:28:46 +0000124static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
125static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
126static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
127static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
128static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
129static void memdbDlClose(sqlite3_vfs*, void*);
130static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
131static int memdbSleep(sqlite3_vfs*, int microseconds);
drh14714162018-03-06 19:14:32 +0000132/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
drhac442f42018-01-03 01:28:46 +0000133static int memdbGetLastError(sqlite3_vfs*, int, char *);
134static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
135
136static sqlite3_vfs memdb_vfs = {
137 2, /* iVersion */
138 0, /* szOsFile (set when registered) */
139 1024, /* mxPathname */
140 0, /* pNext */
141 "memdb", /* zName */
142 0, /* pAppData (set when registered) */
143 memdbOpen, /* xOpen */
drh14714162018-03-06 19:14:32 +0000144 0, /* memdbDelete, */ /* xDelete */
drhac442f42018-01-03 01:28:46 +0000145 memdbAccess, /* xAccess */
146 memdbFullPathname, /* xFullPathname */
147 memdbDlOpen, /* xDlOpen */
148 memdbDlError, /* xDlError */
149 memdbDlSym, /* xDlSym */
150 memdbDlClose, /* xDlClose */
151 memdbRandomness, /* xRandomness */
152 memdbSleep, /* xSleep */
drh14714162018-03-06 19:14:32 +0000153 0, /* memdbCurrentTime, */ /* xCurrentTime */
drhac442f42018-01-03 01:28:46 +0000154 memdbGetLastError, /* xGetLastError */
drh904e48e2021-05-17 17:14:38 +0000155 memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
156 0, /* xSetSystemCall */
157 0, /* xGetSystemCall */
158 0, /* xNextSystemCall */
drhac442f42018-01-03 01:28:46 +0000159};
160
161static const sqlite3_io_methods memdb_io_methods = {
162 3, /* iVersion */
163 memdbClose, /* xClose */
164 memdbRead, /* xRead */
165 memdbWrite, /* xWrite */
166 memdbTruncate, /* xTruncate */
167 memdbSync, /* xSync */
168 memdbFileSize, /* xFileSize */
169 memdbLock, /* xLock */
170 memdbLock, /* xUnlock - same as xLock in this case */
drh14714162018-03-06 19:14:32 +0000171 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
drhac442f42018-01-03 01:28:46 +0000172 memdbFileControl, /* xFileControl */
drh5f9d1922018-03-06 04:01:08 +0000173 0, /* memdbSectorSize,*/ /* xSectorSize */
drhac442f42018-01-03 01:28:46 +0000174 memdbDeviceCharacteristics, /* xDeviceCharacteristics */
drh99abe5c2018-01-03 22:48:38 +0000175 0, /* xShmMap */
176 0, /* xShmLock */
177 0, /* xShmBarrier */
178 0, /* xShmUnmap */
drhac442f42018-01-03 01:28:46 +0000179 memdbFetch, /* xFetch */
180 memdbUnfetch /* xUnfetch */
181};
182
drh2f4d0ec2021-05-10 23:48:46 +0000183/*
184** Enter/leave the mutex on a MemStore
185*/
drh904e48e2021-05-17 17:14:38 +0000186#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
187static void memdbEnter(MemStore *p){
188 UNUSED_PARAMETER(p);
189}
190static void memdbLeave(MemStore *p){
191 UNUSED_PARAMETER(p);
192}
193#else
drh2f4d0ec2021-05-10 23:48:46 +0000194static void memdbEnter(MemStore *p){
195 sqlite3_mutex_enter(p->pMutex);
196}
197static void memdbLeave(MemStore *p){
198 sqlite3_mutex_leave(p->pMutex);
199}
drh904e48e2021-05-17 17:14:38 +0000200#endif
drh2f4d0ec2021-05-10 23:48:46 +0000201
drhac442f42018-01-03 01:28:46 +0000202
203
204/*
205** Close an memdb-file.
drh2f4d0ec2021-05-10 23:48:46 +0000206** Free the underlying MemStore object when its refcount drops to zero
207** or less.
drhac442f42018-01-03 01:28:46 +0000208*/
209static int memdbClose(sqlite3_file *pFile){
drh2f4d0ec2021-05-10 23:48:46 +0000210 MemStore *p = ((MemFile*)pFile)->pStore;
drh52d14072021-05-12 15:39:02 +0000211 if( p->zFName ){
212 int i;
drh2d344f92021-05-12 02:52:20 +0000213#ifndef SQLITE_MUTEX_OMIT
drh52d14072021-05-12 15:39:02 +0000214 sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
drh2d344f92021-05-12 02:52:20 +0000215#endif
drh52d14072021-05-12 15:39:02 +0000216 sqlite3_mutex_enter(pVfsMutex);
217 for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
218 if( memdb_g.apMemStore[i]==p ){
219 memdbEnter(p);
220 if( p->nRef==1 ){
drh2f4d0ec2021-05-10 23:48:46 +0000221 memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
222 if( memdb_g.nMemStore==0 ){
223 sqlite3_free(memdb_g.apMemStore);
224 memdb_g.apMemStore = 0;
225 }
drh2f4d0ec2021-05-10 23:48:46 +0000226 }
drh52d14072021-05-12 15:39:02 +0000227 break;
drh2f4d0ec2021-05-10 23:48:46 +0000228 }
drh52d14072021-05-12 15:39:02 +0000229 }
230 sqlite3_mutex_leave(pVfsMutex);
231 }else{
232 memdbEnter(p);
233 }
234 p->nRef--;
235 if( p->nRef<=0 ){
236 if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
237 sqlite3_free(p->aData);
drh2f4d0ec2021-05-10 23:48:46 +0000238 }
239 memdbLeave(p);
240 sqlite3_mutex_free(p->pMutex);
241 sqlite3_free(p);
242 }else{
243 memdbLeave(p);
drhff01ee32020-10-17 22:13:16 +0000244 }
drhac442f42018-01-03 01:28:46 +0000245 return SQLITE_OK;
246}
247
248/*
249** Read data from an memdb-file.
250*/
251static int memdbRead(
252 sqlite3_file *pFile,
253 void *zBuf,
254 int iAmt,
255 sqlite_int64 iOfst
256){
drh2f4d0ec2021-05-10 23:48:46 +0000257 MemStore *p = ((MemFile*)pFile)->pStore;
258 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000259 if( iOfst+iAmt>p->sz ){
260 memset(zBuf, 0, iAmt);
drhcb7d5412018-01-03 16:49:52 +0000261 if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
drh2f4d0ec2021-05-10 23:48:46 +0000262 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000263 return SQLITE_IOERR_SHORT_READ;
264 }
265 memcpy(zBuf, p->aData+iOfst, iAmt);
drh2f4d0ec2021-05-10 23:48:46 +0000266 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000267 return SQLITE_OK;
268}
269
270/*
271** Try to enlarge the memory allocation to hold at least sz bytes
272*/
drh2f4d0ec2021-05-10 23:48:46 +0000273static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
drhac442f42018-01-03 01:28:46 +0000274 unsigned char *pNew;
drh88944e62021-10-23 17:46:00 +0000275 if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
drh5f9d1922018-03-06 04:01:08 +0000276 return SQLITE_FULL;
277 }
drh6ca64482019-01-22 16:06:20 +0000278 if( newSz>p->szMax ){
279 return SQLITE_FULL;
280 }
281 newSz *= 2;
282 if( newSz>p->szMax ) newSz = p->szMax;
drhd924e7b2020-05-17 00:26:44 +0000283 pNew = sqlite3Realloc(p->aData, newSz);
dana3a91dd2021-04-09 20:50:40 +0000284 if( pNew==0 ) return SQLITE_IOERR_NOMEM;
drhac442f42018-01-03 01:28:46 +0000285 p->aData = pNew;
drh6ca64482019-01-22 16:06:20 +0000286 p->szAlloc = newSz;
drhac442f42018-01-03 01:28:46 +0000287 return SQLITE_OK;
288}
289
290/*
291** Write data to an memdb-file.
292*/
293static int memdbWrite(
294 sqlite3_file *pFile,
295 const void *z,
296 int iAmt,
297 sqlite_int64 iOfst
298){
drh2f4d0ec2021-05-10 23:48:46 +0000299 MemStore *p = ((MemFile*)pFile)->pStore;
300 memdbEnter(p);
drh483051c2021-05-12 02:09:01 +0000301 if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
302 /* Can't happen: memdbLock() will return SQLITE_READONLY before
303 ** reaching this point */
drh2f4d0ec2021-05-10 23:48:46 +0000304 memdbLeave(p);
305 return SQLITE_IOERR_WRITE;
306 }
drhac442f42018-01-03 01:28:46 +0000307 if( iOfst+iAmt>p->sz ){
drh5f9d1922018-03-06 04:01:08 +0000308 int rc;
drh6ca64482019-01-22 16:06:20 +0000309 if( iOfst+iAmt>p->szAlloc
310 && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
drh5f9d1922018-03-06 04:01:08 +0000311 ){
drh2f4d0ec2021-05-10 23:48:46 +0000312 memdbLeave(p);
drh5f9d1922018-03-06 04:01:08 +0000313 return rc;
drhac442f42018-01-03 01:28:46 +0000314 }
315 if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
316 p->sz = iOfst+iAmt;
317 }
318 memcpy(p->aData+iOfst, z, iAmt);
drh2f4d0ec2021-05-10 23:48:46 +0000319 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000320 return SQLITE_OK;
321}
322
323/*
324** Truncate an memdb-file.
drh14714162018-03-06 19:14:32 +0000325**
326** In rollback mode (which is always the case for memdb, as it does not
327** support WAL mode) the truncate() method is only used to reduce
328** the size of a file, never to increase the size.
drhac442f42018-01-03 01:28:46 +0000329*/
330static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
drh2f4d0ec2021-05-10 23:48:46 +0000331 MemStore *p = ((MemFile*)pFile)->pStore;
332 int rc = SQLITE_OK;
333 memdbEnter(p);
dan1a39e452021-11-08 15:46:08 +0000334 if( size>p->sz ){
335 /* This can only happen with a corrupt wal mode db */
336 rc = SQLITE_CORRUPT;
drh2f4d0ec2021-05-10 23:48:46 +0000337 }else{
338 p->sz = size;
339 }
340 memdbLeave(p);
341 return rc;
drhac442f42018-01-03 01:28:46 +0000342}
343
344/*
345** Sync an memdb-file.
346*/
347static int memdbSync(sqlite3_file *pFile, int flags){
drh904e48e2021-05-17 17:14:38 +0000348 UNUSED_PARAMETER(pFile);
349 UNUSED_PARAMETER(flags);
drhac442f42018-01-03 01:28:46 +0000350 return SQLITE_OK;
351}
352
353/*
354** Return the current file-size of an memdb-file.
355*/
356static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
drh2f4d0ec2021-05-10 23:48:46 +0000357 MemStore *p = ((MemFile*)pFile)->pStore;
358 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000359 *pSize = p->sz;
drh2f4d0ec2021-05-10 23:48:46 +0000360 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000361 return SQLITE_OK;
362}
363
364/*
365** Lock an memdb-file.
366*/
367static int memdbLock(sqlite3_file *pFile, int eLock){
drh2f4d0ec2021-05-10 23:48:46 +0000368 MemFile *pThis = (MemFile*)pFile;
369 MemStore *p = pThis->pStore;
370 int rc = SQLITE_OK;
371 if( eLock==pThis->eLock ) return SQLITE_OK;
372 memdbEnter(p);
373 if( eLock>SQLITE_LOCK_SHARED ){
374 if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
375 rc = SQLITE_READONLY;
376 }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
377 if( p->nWrLock ){
378 rc = SQLITE_BUSY;
379 }else{
380 p->nWrLock = 1;
381 }
382 }
383 }else if( eLock==SQLITE_LOCK_SHARED ){
384 if( pThis->eLock > SQLITE_LOCK_SHARED ){
385 assert( p->nWrLock==1 );
386 p->nWrLock = 0;
387 }else if( p->nWrLock ){
388 rc = SQLITE_BUSY;
389 }else{
390 p->nRdLock++;
391 }
392 }else{
393 assert( eLock==SQLITE_LOCK_NONE );
394 if( pThis->eLock>SQLITE_LOCK_SHARED ){
395 assert( p->nWrLock==1 );
396 p->nWrLock = 0;
397 }
398 assert( p->nRdLock>0 );
399 p->nRdLock--;
drhf186f0b2019-01-22 16:43:47 +0000400 }
drh2f4d0ec2021-05-10 23:48:46 +0000401 if( rc==SQLITE_OK ) pThis->eLock = eLock;
402 memdbLeave(p);
403 return rc;
drhac442f42018-01-03 01:28:46 +0000404}
405
drh2f4d0ec2021-05-10 23:48:46 +0000406#if 0
drhac442f42018-01-03 01:28:46 +0000407/*
drh2f4d0ec2021-05-10 23:48:46 +0000408** This interface is only used for crash recovery, which does not
409** occur on an in-memory database.
drhac442f42018-01-03 01:28:46 +0000410*/
411static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
412 *pResOut = 0;
413 return SQLITE_OK;
414}
drh14714162018-03-06 19:14:32 +0000415#endif
drhac442f42018-01-03 01:28:46 +0000416
drh2f4d0ec2021-05-10 23:48:46 +0000417
drhac442f42018-01-03 01:28:46 +0000418/*
419** File control method. For custom operations on an memdb-file.
420*/
421static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
drh2f4d0ec2021-05-10 23:48:46 +0000422 MemStore *p = ((MemFile*)pFile)->pStore;
drhac442f42018-01-03 01:28:46 +0000423 int rc = SQLITE_NOTFOUND;
drh2f4d0ec2021-05-10 23:48:46 +0000424 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000425 if( op==SQLITE_FCNTL_VFSNAME ){
426 *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
427 rc = SQLITE_OK;
428 }
drh6ca64482019-01-22 16:06:20 +0000429 if( op==SQLITE_FCNTL_SIZE_LIMIT ){
430 sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
431 if( iLimit<p->sz ){
432 if( iLimit<0 ){
433 iLimit = p->szMax;
434 }else{
435 iLimit = p->sz;
436 }
437 }
438 p->szMax = iLimit;
439 *(sqlite3_int64*)pArg = iLimit;
440 rc = SQLITE_OK;
441 }
drh2f4d0ec2021-05-10 23:48:46 +0000442 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000443 return rc;
444}
445
drh5f9d1922018-03-06 04:01:08 +0000446#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
drhac442f42018-01-03 01:28:46 +0000447/*
448** Return the sector-size in bytes for an memdb-file.
449*/
450static int memdbSectorSize(sqlite3_file *pFile){
451 return 1024;
452}
drh5f9d1922018-03-06 04:01:08 +0000453#endif
drhac442f42018-01-03 01:28:46 +0000454
455/*
456** Return the device characteristic flags supported by an memdb-file.
457*/
458static int memdbDeviceCharacteristics(sqlite3_file *pFile){
drh904e48e2021-05-17 17:14:38 +0000459 UNUSED_PARAMETER(pFile);
drhac442f42018-01-03 01:28:46 +0000460 return SQLITE_IOCAP_ATOMIC |
461 SQLITE_IOCAP_POWERSAFE_OVERWRITE |
462 SQLITE_IOCAP_SAFE_APPEND |
463 SQLITE_IOCAP_SEQUENTIAL;
464}
465
drhac442f42018-01-03 01:28:46 +0000466/* Fetch a page of a memory-mapped file */
467static int memdbFetch(
468 sqlite3_file *pFile,
469 sqlite3_int64 iOfst,
470 int iAmt,
471 void **pp
472){
drh2f4d0ec2021-05-10 23:48:46 +0000473 MemStore *p = ((MemFile*)pFile)->pStore;
474 memdbEnter(p);
drh88944e62021-10-23 17:46:00 +0000475 if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
drh94f0a832019-01-25 14:16:01 +0000476 *pp = 0;
477 }else{
478 p->nMmap++;
479 *pp = (void*)(p->aData + iOfst);
480 }
drh2f4d0ec2021-05-10 23:48:46 +0000481 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000482 return SQLITE_OK;
483}
484
485/* Release a memory-mapped page */
486static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
drh2f4d0ec2021-05-10 23:48:46 +0000487 MemStore *p = ((MemFile*)pFile)->pStore;
drh904e48e2021-05-17 17:14:38 +0000488 UNUSED_PARAMETER(iOfst);
489 UNUSED_PARAMETER(pPage);
drh2f4d0ec2021-05-10 23:48:46 +0000490 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000491 p->nMmap--;
drh2f4d0ec2021-05-10 23:48:46 +0000492 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000493 return SQLITE_OK;
494}
495
496/*
497** Open an mem file handle.
498*/
499static int memdbOpen(
500 sqlite3_vfs *pVfs,
501 const char *zName,
drh2f4d0ec2021-05-10 23:48:46 +0000502 sqlite3_file *pFd,
drhac442f42018-01-03 01:28:46 +0000503 int flags,
504 int *pOutFlags
505){
drh2f4d0ec2021-05-10 23:48:46 +0000506 MemFile *pFile = (MemFile*)pFd;
507 MemStore *p = 0;
508 int szName;
drh90385dd2021-10-27 15:19:01 +0000509 UNUSED_PARAMETER(pVfs);
drh88944e62021-10-23 17:46:00 +0000510
larrybr3a9793e2021-09-10 18:35:59 +0000511 memset(pFile, 0, sizeof(*pFile));
drh2f4d0ec2021-05-10 23:48:46 +0000512 szName = sqlite3Strlen30(zName);
513 if( szName>1 && zName[0]=='/' ){
514 int i;
drh2d344f92021-05-12 02:52:20 +0000515#ifndef SQLITE_MUTEX_OMIT
drh2f4d0ec2021-05-10 23:48:46 +0000516 sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
drh2d344f92021-05-12 02:52:20 +0000517#endif
drh2f4d0ec2021-05-10 23:48:46 +0000518 sqlite3_mutex_enter(pVfsMutex);
519 for(i=0; i<memdb_g.nMemStore; i++){
520 if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
521 p = memdb_g.apMemStore[i];
522 break;
523 }
524 }
525 if( p==0 ){
526 MemStore **apNew;
527 p = sqlite3Malloc( sizeof(*p) + szName + 3 );
528 if( p==0 ){
529 sqlite3_mutex_leave(pVfsMutex);
530 return SQLITE_NOMEM;
531 }
532 apNew = sqlite3Realloc(memdb_g.apMemStore,
533 sizeof(apNew[0])*(memdb_g.nMemStore+1) );
534 if( apNew==0 ){
535 sqlite3_free(p);
536 sqlite3_mutex_leave(pVfsMutex);
537 return SQLITE_NOMEM;
538 }
539 apNew[memdb_g.nMemStore++] = p;
540 memdb_g.apMemStore = apNew;
541 memset(p, 0, sizeof(*p));
542 p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
543 p->szMax = sqlite3GlobalConfig.mxMemdbSize;
544 p->zFName = (char*)&p[1];
545 memcpy(p->zFName, zName, szName+1);
546 p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
drh2d344f92021-05-12 02:52:20 +0000547 if( p->pMutex==0 ){
548 memdb_g.nMemStore--;
549 sqlite3_free(p);
550 sqlite3_mutex_leave(pVfsMutex);
551 return SQLITE_NOMEM;
552 }
drh2f4d0ec2021-05-10 23:48:46 +0000553 p->nRef = 1;
554 memdbEnter(p);
555 }else{
556 memdbEnter(p);
557 p->nRef++;
558 }
559 sqlite3_mutex_leave(pVfsMutex);
560 }else{
561 p = sqlite3Malloc( sizeof(*p) );
562 if( p==0 ){
563 return SQLITE_NOMEM;
564 }
565 memset(p, 0, sizeof(*p));
566 p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
567 p->szMax = sqlite3GlobalConfig.mxMemdbSize;
568 }
569 pFile->pStore = p;
drh88944e62021-10-23 17:46:00 +0000570 if( pOutFlags!=0 ){
571 *pOutFlags = flags | SQLITE_OPEN_MEMORY;
572 }
drh2f4d0ec2021-05-10 23:48:46 +0000573 pFd->pMethods = &memdb_io_methods;
574 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000575 return SQLITE_OK;
576}
577
drh067b92b2020-06-19 15:24:12 +0000578#if 0 /* Only used to delete rollback journals, super-journals, and WAL
drh14714162018-03-06 19:14:32 +0000579 ** files, none of which exist in memdb. So this routine is never used */
drhac442f42018-01-03 01:28:46 +0000580/*
581** Delete the file located at zPath. If the dirSync argument is true,
582** ensure the file-system modifications are synced to disk before
583** returning.
584*/
585static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
586 return SQLITE_IOERR_DELETE;
587}
drh14714162018-03-06 19:14:32 +0000588#endif
drhac442f42018-01-03 01:28:46 +0000589
590/*
591** Test for access permissions. Return true if the requested permission
592** is available, or false otherwise.
drh14714162018-03-06 19:14:32 +0000593**
594** With memdb, no files ever exist on disk. So always return false.
drhac442f42018-01-03 01:28:46 +0000595*/
596static int memdbAccess(
597 sqlite3_vfs *pVfs,
598 const char *zPath,
599 int flags,
600 int *pResOut
601){
drh904e48e2021-05-17 17:14:38 +0000602 UNUSED_PARAMETER(pVfs);
603 UNUSED_PARAMETER(zPath);
604 UNUSED_PARAMETER(flags);
drhac442f42018-01-03 01:28:46 +0000605 *pResOut = 0;
606 return SQLITE_OK;
607}
608
609/*
610** Populate buffer zOut with the full canonical pathname corresponding
611** to the pathname in zPath. zOut is guaranteed to point to a buffer
612** of at least (INST_MAX_PATHNAME+1) bytes.
613*/
614static int memdbFullPathname(
615 sqlite3_vfs *pVfs,
616 const char *zPath,
617 int nOut,
618 char *zOut
619){
drh904e48e2021-05-17 17:14:38 +0000620 UNUSED_PARAMETER(pVfs);
drhac442f42018-01-03 01:28:46 +0000621 sqlite3_snprintf(nOut, zOut, "%s", zPath);
622 return SQLITE_OK;
623}
624
625/*
626** Open the dynamic library located at zPath and return a handle.
627*/
628static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
629 return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
630}
631
632/*
633** Populate the buffer zErrMsg (size nByte bytes) with a human readable
634** utf-8 string describing the most recent error encountered associated
635** with dynamic libraries.
636*/
637static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
638 ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
639}
640
641/*
642** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
643*/
644static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
645 return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
646}
647
648/*
649** Close the dynamic library handle pHandle.
650*/
651static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
652 ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
653}
654
655/*
656** Populate the buffer pointed to by zBufOut with nByte bytes of
657** random data.
658*/
659static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
660 return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
661}
662
663/*
664** Sleep for nMicro microseconds. Return the number of microseconds
665** actually slept.
666*/
667static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
668 return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
669}
670
drh14714162018-03-06 19:14:32 +0000671#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
drhac442f42018-01-03 01:28:46 +0000672/*
673** Return the current time as a Julian Day number in *pTimeOut.
674*/
675static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
676 return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
677}
drh14714162018-03-06 19:14:32 +0000678#endif
drhac442f42018-01-03 01:28:46 +0000679
680static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
681 return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
682}
683static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
684 return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
685}
686
687/*
688** Translate a database connection pointer and schema name into a
689** MemFile pointer.
690*/
691static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
692 MemFile *p = 0;
drh2f4d0ec2021-05-10 23:48:46 +0000693 MemStore *pStore;
drhac442f42018-01-03 01:28:46 +0000694 int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
695 if( rc ) return 0;
696 if( p->base.pMethods!=&memdb_io_methods ) return 0;
drh2f4d0ec2021-05-10 23:48:46 +0000697 pStore = p->pStore;
698 memdbEnter(pStore);
699 if( pStore->zFName!=0 ) p = 0;
700 memdbLeave(pStore);
drhac442f42018-01-03 01:28:46 +0000701 return p;
702}
703
704/*
drhcb7d5412018-01-03 16:49:52 +0000705** Return the serialization of a database
706*/
707unsigned char *sqlite3_serialize(
708 sqlite3 *db, /* The database connection */
709 const char *zSchema, /* Which database within the connection */
710 sqlite3_int64 *piSize, /* Write size here, if not NULL */
711 unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
712){
drhb2194ce2018-03-01 22:18:26 +0000713 MemFile *p;
714 int iDb;
drhcb7d5412018-01-03 16:49:52 +0000715 Btree *pBt;
716 sqlite3_int64 sz;
717 int szPage = 0;
718 sqlite3_stmt *pStmt = 0;
719 unsigned char *pOut;
720 char *zSql;
721 int rc;
722
mistachkin6630f942018-03-08 19:56:52 +0000723#ifdef SQLITE_ENABLE_API_ARMOR
724 if( !sqlite3SafetyCheckOk(db) ){
725 (void)SQLITE_MISUSE_BKPT;
726 return 0;
727 }
728#endif
729
drhb2194ce2018-03-01 22:18:26 +0000730 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
731 p = memdbFromDbSchema(db, zSchema);
732 iDb = sqlite3FindDbName(db, zSchema);
drhcb7d5412018-01-03 16:49:52 +0000733 if( piSize ) *piSize = -1;
734 if( iDb<0 ) return 0;
735 if( p ){
drh2f4d0ec2021-05-10 23:48:46 +0000736 MemStore *pStore = p->pStore;
737 assert( pStore->pMutex==0 );
738 if( piSize ) *piSize = pStore->sz;
drhcb7d5412018-01-03 16:49:52 +0000739 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
drh2f4d0ec2021-05-10 23:48:46 +0000740 pOut = pStore->aData;
drhcb7d5412018-01-03 16:49:52 +0000741 }else{
drh2f4d0ec2021-05-10 23:48:46 +0000742 pOut = sqlite3_malloc64( pStore->sz );
743 if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
drhcb7d5412018-01-03 16:49:52 +0000744 }
745 return pOut;
746 }
747 pBt = db->aDb[iDb].pBt;
748 if( pBt==0 ) return 0;
749 szPage = sqlite3BtreeGetPageSize(pBt);
750 zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
751 rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
752 sqlite3_free(zSql);
753 if( rc ) return 0;
drh8784efa2018-03-06 20:54:27 +0000754 rc = sqlite3_step(pStmt);
755 if( rc!=SQLITE_ROW ){
drhcb7d5412018-01-03 16:49:52 +0000756 pOut = 0;
757 }else{
drh8784efa2018-03-06 20:54:27 +0000758 sz = sqlite3_column_int64(pStmt, 0)*szPage;
759 if( piSize ) *piSize = sz;
760 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
761 pOut = 0;
762 }else{
763 pOut = sqlite3_malloc64( sz );
764 if( pOut ){
765 int nPage = sqlite3_column_int(pStmt, 0);
766 Pager *pPager = sqlite3BtreePager(pBt);
767 int pgno;
768 for(pgno=1; pgno<=nPage; pgno++){
769 DbPage *pPage = 0;
770 unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
771 rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
772 if( rc==SQLITE_OK ){
773 memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
774 }else{
775 memset(pTo, 0, szPage);
776 }
777 sqlite3PagerUnref(pPage);
drhcb7d5412018-01-03 16:49:52 +0000778 }
drhcb7d5412018-01-03 16:49:52 +0000779 }
780 }
781 }
782 sqlite3_finalize(pStmt);
783 return pOut;
784}
785
drh3ec86652018-01-03 19:03:31 +0000786/* Convert zSchema to a MemDB and initialize its content.
787*/
788int sqlite3_deserialize(
789 sqlite3 *db, /* The database connection */
790 const char *zSchema, /* Which DB to reopen with the deserialization */
791 unsigned char *pData, /* The serialized database content */
792 sqlite3_int64 szDb, /* Number bytes in the deserialization */
793 sqlite3_int64 szBuf, /* Total size of buffer pData[] */
794 unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
795){
796 MemFile *p;
797 char *zSql;
798 sqlite3_stmt *pStmt = 0;
799 int rc;
800 int iDb;
801
mistachkin6630f942018-03-08 19:56:52 +0000802#ifdef SQLITE_ENABLE_API_ARMOR
803 if( !sqlite3SafetyCheckOk(db) ){
804 return SQLITE_MISUSE_BKPT;
805 }
806 if( szDb<0 ) return SQLITE_MISUSE_BKPT;
807 if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
808#endif
809
drh3ec86652018-01-03 19:03:31 +0000810 sqlite3_mutex_enter(db->mutex);
811 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
812 iDb = sqlite3FindDbName(db, zSchema);
drh53fa0252021-07-20 02:02:24 +0000813 testcase( iDb==1 );
814 if( iDb<2 && iDb!=0 ){
drh3ec86652018-01-03 19:03:31 +0000815 rc = SQLITE_ERROR;
816 goto end_deserialize;
drh53fa0252021-07-20 02:02:24 +0000817 }
drh3ec86652018-01-03 19:03:31 +0000818 zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
drh672f07c2020-10-20 14:40:53 +0000819 if( zSql==0 ){
820 rc = SQLITE_NOMEM;
821 }else{
822 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
823 sqlite3_free(zSql);
824 }
drh3ec86652018-01-03 19:03:31 +0000825 if( rc ) goto end_deserialize;
826 db->init.iDb = (u8)iDb;
827 db->init.reopenMemdb = 1;
828 rc = sqlite3_step(pStmt);
829 db->init.reopenMemdb = 0;
830 if( rc!=SQLITE_DONE ){
831 rc = SQLITE_ERROR;
832 goto end_deserialize;
833 }
834 p = memdbFromDbSchema(db, zSchema);
drh8784efa2018-03-06 20:54:27 +0000835 if( p==0 ){
836 rc = SQLITE_ERROR;
837 }else{
drh2f4d0ec2021-05-10 23:48:46 +0000838 MemStore *pStore = p->pStore;
839 pStore->aData = pData;
drhff01ee32020-10-17 22:13:16 +0000840 pData = 0;
drh2f4d0ec2021-05-10 23:48:46 +0000841 pStore->sz = szDb;
842 pStore->szAlloc = szBuf;
843 pStore->szMax = szBuf;
844 if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
845 pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
drh6ca64482019-01-22 16:06:20 +0000846 }
drh2f4d0ec2021-05-10 23:48:46 +0000847 pStore->mFlags = mFlags;
drh8784efa2018-03-06 20:54:27 +0000848 rc = SQLITE_OK;
849 }
850
drh3ec86652018-01-03 19:03:31 +0000851end_deserialize:
852 sqlite3_finalize(pStmt);
drhff01ee32020-10-17 22:13:16 +0000853 if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
854 sqlite3_free(pData);
855 }
drh3ec86652018-01-03 19:03:31 +0000856 sqlite3_mutex_leave(db->mutex);
857 return rc;
858}
859
drhac442f42018-01-03 01:28:46 +0000860/*
861** This routine is called when the extension is loaded.
862** Register the new VFS.
863*/
864int sqlite3MemdbInit(void){
drh5f9d1922018-03-06 04:01:08 +0000865 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000866 unsigned int sz;
867 if( NEVER(pLower==0) ) return SQLITE_ERROR;
868 sz = pLower->szOsFile;
drh5f9d1922018-03-06 04:01:08 +0000869 memdb_vfs.pAppData = pLower;
drhf25f8d52020-05-21 20:38:39 +0000870 /* The following conditional can only be true when compiled for
871 ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
872 ** it in, to be safe, but it is marked as NO_TEST since there
873 ** is no way to reach it under most builds. */
874 if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
drh5f9d1922018-03-06 04:01:08 +0000875 memdb_vfs.szOsFile = sz;
drhac442f42018-01-03 01:28:46 +0000876 return sqlite3_vfs_register(&memdb_vfs, 0);
877}
drh8d889af2021-05-08 17:18:23 +0000878#endif /* SQLITE_OMIT_DESERIALIZE */