blob: 657cb9ca654d0f12bffe555147ed4b7e0f4da25b [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);
dan1532f9d2022-12-19 14:06:36 +0000112static int memdbUnlock(sqlite3_file*, int);
drh14714162018-03-06 19:14:32 +0000113/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
drhac442f42018-01-03 01:28:46 +0000114static int memdbFileControl(sqlite3_file*, int op, void *pArg);
drh5f9d1922018-03-06 04:01:08 +0000115/* static int memdbSectorSize(sqlite3_file*); // not used */
drhac442f42018-01-03 01:28:46 +0000116static int memdbDeviceCharacteristics(sqlite3_file*);
drhac442f42018-01-03 01:28:46 +0000117static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
118static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
119
120/*
121** Methods for MemVfs
122*/
123static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
drh14714162018-03-06 19:14:32 +0000124/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
drhac442f42018-01-03 01:28:46 +0000125static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
126static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
127static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
128static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
129static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
130static void memdbDlClose(sqlite3_vfs*, void*);
131static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
132static int memdbSleep(sqlite3_vfs*, int microseconds);
drh14714162018-03-06 19:14:32 +0000133/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
drhac442f42018-01-03 01:28:46 +0000134static int memdbGetLastError(sqlite3_vfs*, int, char *);
135static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
136
137static sqlite3_vfs memdb_vfs = {
138 2, /* iVersion */
139 0, /* szOsFile (set when registered) */
140 1024, /* mxPathname */
141 0, /* pNext */
142 "memdb", /* zName */
143 0, /* pAppData (set when registered) */
144 memdbOpen, /* xOpen */
drh14714162018-03-06 19:14:32 +0000145 0, /* memdbDelete, */ /* xDelete */
drhac442f42018-01-03 01:28:46 +0000146 memdbAccess, /* xAccess */
147 memdbFullPathname, /* xFullPathname */
148 memdbDlOpen, /* xDlOpen */
149 memdbDlError, /* xDlError */
150 memdbDlSym, /* xDlSym */
151 memdbDlClose, /* xDlClose */
152 memdbRandomness, /* xRandomness */
153 memdbSleep, /* xSleep */
drh14714162018-03-06 19:14:32 +0000154 0, /* memdbCurrentTime, */ /* xCurrentTime */
drhac442f42018-01-03 01:28:46 +0000155 memdbGetLastError, /* xGetLastError */
drh904e48e2021-05-17 17:14:38 +0000156 memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
157 0, /* xSetSystemCall */
158 0, /* xGetSystemCall */
159 0, /* xNextSystemCall */
drhac442f42018-01-03 01:28:46 +0000160};
161
162static const sqlite3_io_methods memdb_io_methods = {
163 3, /* iVersion */
164 memdbClose, /* xClose */
165 memdbRead, /* xRead */
166 memdbWrite, /* xWrite */
167 memdbTruncate, /* xTruncate */
168 memdbSync, /* xSync */
169 memdbFileSize, /* xFileSize */
170 memdbLock, /* xLock */
dan1532f9d2022-12-19 14:06:36 +0000171 memdbUnlock, /* xUnlock */
drh14714162018-03-06 19:14:32 +0000172 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
drhac442f42018-01-03 01:28:46 +0000173 memdbFileControl, /* xFileControl */
drh5f9d1922018-03-06 04:01:08 +0000174 0, /* memdbSectorSize,*/ /* xSectorSize */
drhac442f42018-01-03 01:28:46 +0000175 memdbDeviceCharacteristics, /* xDeviceCharacteristics */
drh99abe5c2018-01-03 22:48:38 +0000176 0, /* xShmMap */
177 0, /* xShmLock */
178 0, /* xShmBarrier */
179 0, /* xShmUnmap */
drhac442f42018-01-03 01:28:46 +0000180 memdbFetch, /* xFetch */
181 memdbUnfetch /* xUnfetch */
182};
183
drh2f4d0ec2021-05-10 23:48:46 +0000184/*
185** Enter/leave the mutex on a MemStore
186*/
drh904e48e2021-05-17 17:14:38 +0000187#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
188static void memdbEnter(MemStore *p){
189 UNUSED_PARAMETER(p);
190}
191static void memdbLeave(MemStore *p){
192 UNUSED_PARAMETER(p);
193}
194#else
drh2f4d0ec2021-05-10 23:48:46 +0000195static void memdbEnter(MemStore *p){
196 sqlite3_mutex_enter(p->pMutex);
197}
198static void memdbLeave(MemStore *p){
199 sqlite3_mutex_leave(p->pMutex);
200}
drh904e48e2021-05-17 17:14:38 +0000201#endif
drh2f4d0ec2021-05-10 23:48:46 +0000202
drhac442f42018-01-03 01:28:46 +0000203
204
205/*
206** Close an memdb-file.
drh2f4d0ec2021-05-10 23:48:46 +0000207** Free the underlying MemStore object when its refcount drops to zero
208** or less.
drhac442f42018-01-03 01:28:46 +0000209*/
210static int memdbClose(sqlite3_file *pFile){
drh2f4d0ec2021-05-10 23:48:46 +0000211 MemStore *p = ((MemFile*)pFile)->pStore;
drh52d14072021-05-12 15:39:02 +0000212 if( p->zFName ){
213 int i;
drh2d344f92021-05-12 02:52:20 +0000214#ifndef SQLITE_MUTEX_OMIT
drh52d14072021-05-12 15:39:02 +0000215 sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
drh2d344f92021-05-12 02:52:20 +0000216#endif
drh52d14072021-05-12 15:39:02 +0000217 sqlite3_mutex_enter(pVfsMutex);
218 for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
219 if( memdb_g.apMemStore[i]==p ){
220 memdbEnter(p);
221 if( p->nRef==1 ){
drh2f4d0ec2021-05-10 23:48:46 +0000222 memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
223 if( memdb_g.nMemStore==0 ){
224 sqlite3_free(memdb_g.apMemStore);
225 memdb_g.apMemStore = 0;
226 }
drh2f4d0ec2021-05-10 23:48:46 +0000227 }
drh52d14072021-05-12 15:39:02 +0000228 break;
drh2f4d0ec2021-05-10 23:48:46 +0000229 }
drh52d14072021-05-12 15:39:02 +0000230 }
231 sqlite3_mutex_leave(pVfsMutex);
232 }else{
233 memdbEnter(p);
234 }
235 p->nRef--;
236 if( p->nRef<=0 ){
237 if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
238 sqlite3_free(p->aData);
drh2f4d0ec2021-05-10 23:48:46 +0000239 }
240 memdbLeave(p);
241 sqlite3_mutex_free(p->pMutex);
242 sqlite3_free(p);
243 }else{
244 memdbLeave(p);
drhff01ee32020-10-17 22:13:16 +0000245 }
drhac442f42018-01-03 01:28:46 +0000246 return SQLITE_OK;
247}
248
249/*
250** Read data from an memdb-file.
251*/
252static int memdbRead(
253 sqlite3_file *pFile,
254 void *zBuf,
255 int iAmt,
256 sqlite_int64 iOfst
257){
drh2f4d0ec2021-05-10 23:48:46 +0000258 MemStore *p = ((MemFile*)pFile)->pStore;
259 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000260 if( iOfst+iAmt>p->sz ){
261 memset(zBuf, 0, iAmt);
drhcb7d5412018-01-03 16:49:52 +0000262 if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
drh2f4d0ec2021-05-10 23:48:46 +0000263 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000264 return SQLITE_IOERR_SHORT_READ;
265 }
266 memcpy(zBuf, p->aData+iOfst, iAmt);
drh2f4d0ec2021-05-10 23:48:46 +0000267 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000268 return SQLITE_OK;
269}
270
271/*
272** Try to enlarge the memory allocation to hold at least sz bytes
273*/
drh2f4d0ec2021-05-10 23:48:46 +0000274static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
drhac442f42018-01-03 01:28:46 +0000275 unsigned char *pNew;
drh88944e62021-10-23 17:46:00 +0000276 if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
drh5f9d1922018-03-06 04:01:08 +0000277 return SQLITE_FULL;
278 }
drh6ca64482019-01-22 16:06:20 +0000279 if( newSz>p->szMax ){
280 return SQLITE_FULL;
281 }
282 newSz *= 2;
283 if( newSz>p->szMax ) newSz = p->szMax;
drhd924e7b2020-05-17 00:26:44 +0000284 pNew = sqlite3Realloc(p->aData, newSz);
dana3a91dd2021-04-09 20:50:40 +0000285 if( pNew==0 ) return SQLITE_IOERR_NOMEM;
drhac442f42018-01-03 01:28:46 +0000286 p->aData = pNew;
drh6ca64482019-01-22 16:06:20 +0000287 p->szAlloc = newSz;
drhac442f42018-01-03 01:28:46 +0000288 return SQLITE_OK;
289}
290
291/*
292** Write data to an memdb-file.
293*/
294static int memdbWrite(
295 sqlite3_file *pFile,
296 const void *z,
297 int iAmt,
298 sqlite_int64 iOfst
299){
drh2f4d0ec2021-05-10 23:48:46 +0000300 MemStore *p = ((MemFile*)pFile)->pStore;
301 memdbEnter(p);
drh483051c2021-05-12 02:09:01 +0000302 if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
303 /* Can't happen: memdbLock() will return SQLITE_READONLY before
304 ** reaching this point */
drh2f4d0ec2021-05-10 23:48:46 +0000305 memdbLeave(p);
306 return SQLITE_IOERR_WRITE;
307 }
drhac442f42018-01-03 01:28:46 +0000308 if( iOfst+iAmt>p->sz ){
drh5f9d1922018-03-06 04:01:08 +0000309 int rc;
drh6ca64482019-01-22 16:06:20 +0000310 if( iOfst+iAmt>p->szAlloc
311 && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
drh5f9d1922018-03-06 04:01:08 +0000312 ){
drh2f4d0ec2021-05-10 23:48:46 +0000313 memdbLeave(p);
drh5f9d1922018-03-06 04:01:08 +0000314 return rc;
drhac442f42018-01-03 01:28:46 +0000315 }
316 if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
317 p->sz = iOfst+iAmt;
318 }
319 memcpy(p->aData+iOfst, z, iAmt);
drh2f4d0ec2021-05-10 23:48:46 +0000320 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000321 return SQLITE_OK;
322}
323
324/*
325** Truncate an memdb-file.
drh14714162018-03-06 19:14:32 +0000326**
327** In rollback mode (which is always the case for memdb, as it does not
328** support WAL mode) the truncate() method is only used to reduce
329** the size of a file, never to increase the size.
drhac442f42018-01-03 01:28:46 +0000330*/
331static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
drh2f4d0ec2021-05-10 23:48:46 +0000332 MemStore *p = ((MemFile*)pFile)->pStore;
333 int rc = SQLITE_OK;
334 memdbEnter(p);
dan1a39e452021-11-08 15:46:08 +0000335 if( size>p->sz ){
336 /* This can only happen with a corrupt wal mode db */
337 rc = SQLITE_CORRUPT;
drh2f4d0ec2021-05-10 23:48:46 +0000338 }else{
339 p->sz = size;
340 }
341 memdbLeave(p);
342 return rc;
drhac442f42018-01-03 01:28:46 +0000343}
344
345/*
346** Sync an memdb-file.
347*/
348static int memdbSync(sqlite3_file *pFile, int flags){
drh904e48e2021-05-17 17:14:38 +0000349 UNUSED_PARAMETER(pFile);
350 UNUSED_PARAMETER(flags);
drhac442f42018-01-03 01:28:46 +0000351 return SQLITE_OK;
352}
353
354/*
355** Return the current file-size of an memdb-file.
356*/
357static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
drh2f4d0ec2021-05-10 23:48:46 +0000358 MemStore *p = ((MemFile*)pFile)->pStore;
359 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000360 *pSize = p->sz;
drh2f4d0ec2021-05-10 23:48:46 +0000361 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000362 return SQLITE_OK;
363}
364
365/*
366** Lock an memdb-file.
367*/
368static int memdbLock(sqlite3_file *pFile, int eLock){
drh2f4d0ec2021-05-10 23:48:46 +0000369 MemFile *pThis = (MemFile*)pFile;
370 MemStore *p = pThis->pStore;
371 int rc = SQLITE_OK;
dan1532f9d2022-12-19 14:06:36 +0000372 if( eLock<=pThis->eLock ) return SQLITE_OK;
drh2f4d0ec2021-05-10 23:48:46 +0000373 memdbEnter(p);
drh7c66faa2022-12-07 16:58:04 +0000374
dan1532f9d2022-12-19 14:06:36 +0000375 assert( p->nWrLock==0 || p->nWrLock==1 );
376 assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
377 assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );
drh7c66faa2022-12-07 16:58:04 +0000378
dan1532f9d2022-12-19 14:06:36 +0000379 if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
380 rc = SQLITE_READONLY;
drh2f4d0ec2021-05-10 23:48:46 +0000381 }else{
dan1532f9d2022-12-19 14:06:36 +0000382 switch( eLock ){
383 case SQLITE_LOCK_SHARED: {
384 assert( pThis->eLock==SQLITE_LOCK_NONE );
385 if( p->nWrLock>0 ){
386 rc = SQLITE_BUSY;
387 }else{
388 p->nRdLock++;
389 }
390 break;
391 };
392
393 case SQLITE_LOCK_RESERVED:
394 case SQLITE_LOCK_PENDING: {
395 assert( pThis->eLock>=SQLITE_LOCK_SHARED );
drh2656b1b2022-12-20 15:02:44 +0000396 if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
dan1532f9d2022-12-19 14:06:36 +0000397 if( p->nWrLock>0 ){
398 rc = SQLITE_BUSY;
399 }else{
400 p->nWrLock = 1;
401 }
402 }
403 break;
404 }
405
406 default: {
407 assert( eLock==SQLITE_LOCK_EXCLUSIVE );
408 assert( pThis->eLock>=SQLITE_LOCK_SHARED );
409 if( p->nRdLock>1 ){
410 rc = SQLITE_BUSY;
411 }else if( pThis->eLock==SQLITE_LOCK_SHARED ){
412 p->nWrLock = 1;
413 }
414 break;
415 }
drh2f4d0ec2021-05-10 23:48:46 +0000416 }
drhf186f0b2019-01-22 16:43:47 +0000417 }
drh2f4d0ec2021-05-10 23:48:46 +0000418 if( rc==SQLITE_OK ) pThis->eLock = eLock;
419 memdbLeave(p);
420 return rc;
drhac442f42018-01-03 01:28:46 +0000421}
422
dan1532f9d2022-12-19 14:06:36 +0000423/*
424** Unlock an memdb-file.
425*/
426static int memdbUnlock(sqlite3_file *pFile, int eLock){
427 MemFile *pThis = (MemFile*)pFile;
428 MemStore *p = pThis->pStore;
dan1532f9d2022-12-19 14:06:36 +0000429 if( eLock>=pThis->eLock ) return SQLITE_OK;
430 memdbEnter(p);
431
432 assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
433 if( eLock==SQLITE_LOCK_SHARED ){
drh2656b1b2022-12-20 15:02:44 +0000434 if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
dan1532f9d2022-12-19 14:06:36 +0000435 p->nWrLock--;
436 }
437 }else{
438 if( pThis->eLock>SQLITE_LOCK_SHARED ){
439 p->nWrLock--;
440 }
441 p->nRdLock--;
442 }
443
444 pThis->eLock = eLock;
445 memdbLeave(p);
446 return SQLITE_OK;
447}
448
drh2f4d0ec2021-05-10 23:48:46 +0000449#if 0
drhac442f42018-01-03 01:28:46 +0000450/*
drh2f4d0ec2021-05-10 23:48:46 +0000451** This interface is only used for crash recovery, which does not
452** occur on an in-memory database.
drhac442f42018-01-03 01:28:46 +0000453*/
454static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
455 *pResOut = 0;
456 return SQLITE_OK;
457}
drh14714162018-03-06 19:14:32 +0000458#endif
drhac442f42018-01-03 01:28:46 +0000459
drh2f4d0ec2021-05-10 23:48:46 +0000460
drhac442f42018-01-03 01:28:46 +0000461/*
462** File control method. For custom operations on an memdb-file.
463*/
464static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
drh2f4d0ec2021-05-10 23:48:46 +0000465 MemStore *p = ((MemFile*)pFile)->pStore;
drhac442f42018-01-03 01:28:46 +0000466 int rc = SQLITE_NOTFOUND;
drh2f4d0ec2021-05-10 23:48:46 +0000467 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000468 if( op==SQLITE_FCNTL_VFSNAME ){
469 *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
470 rc = SQLITE_OK;
471 }
drh6ca64482019-01-22 16:06:20 +0000472 if( op==SQLITE_FCNTL_SIZE_LIMIT ){
473 sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
474 if( iLimit<p->sz ){
475 if( iLimit<0 ){
476 iLimit = p->szMax;
477 }else{
478 iLimit = p->sz;
479 }
480 }
481 p->szMax = iLimit;
482 *(sqlite3_int64*)pArg = iLimit;
483 rc = SQLITE_OK;
484 }
drh2f4d0ec2021-05-10 23:48:46 +0000485 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000486 return rc;
487}
488
drh5f9d1922018-03-06 04:01:08 +0000489#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
drhac442f42018-01-03 01:28:46 +0000490/*
491** Return the sector-size in bytes for an memdb-file.
492*/
493static int memdbSectorSize(sqlite3_file *pFile){
494 return 1024;
495}
drh5f9d1922018-03-06 04:01:08 +0000496#endif
drhac442f42018-01-03 01:28:46 +0000497
498/*
499** Return the device characteristic flags supported by an memdb-file.
500*/
501static int memdbDeviceCharacteristics(sqlite3_file *pFile){
drh904e48e2021-05-17 17:14:38 +0000502 UNUSED_PARAMETER(pFile);
drhac442f42018-01-03 01:28:46 +0000503 return SQLITE_IOCAP_ATOMIC |
504 SQLITE_IOCAP_POWERSAFE_OVERWRITE |
505 SQLITE_IOCAP_SAFE_APPEND |
506 SQLITE_IOCAP_SEQUENTIAL;
507}
508
drhac442f42018-01-03 01:28:46 +0000509/* Fetch a page of a memory-mapped file */
510static int memdbFetch(
511 sqlite3_file *pFile,
512 sqlite3_int64 iOfst,
513 int iAmt,
514 void **pp
515){
drh2f4d0ec2021-05-10 23:48:46 +0000516 MemStore *p = ((MemFile*)pFile)->pStore;
517 memdbEnter(p);
drh88944e62021-10-23 17:46:00 +0000518 if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
drh94f0a832019-01-25 14:16:01 +0000519 *pp = 0;
520 }else{
521 p->nMmap++;
522 *pp = (void*)(p->aData + iOfst);
523 }
drh2f4d0ec2021-05-10 23:48:46 +0000524 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000525 return SQLITE_OK;
526}
527
528/* Release a memory-mapped page */
529static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
drh2f4d0ec2021-05-10 23:48:46 +0000530 MemStore *p = ((MemFile*)pFile)->pStore;
drh904e48e2021-05-17 17:14:38 +0000531 UNUSED_PARAMETER(iOfst);
532 UNUSED_PARAMETER(pPage);
drh2f4d0ec2021-05-10 23:48:46 +0000533 memdbEnter(p);
drhac442f42018-01-03 01:28:46 +0000534 p->nMmap--;
drh2f4d0ec2021-05-10 23:48:46 +0000535 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000536 return SQLITE_OK;
537}
538
539/*
540** Open an mem file handle.
541*/
542static int memdbOpen(
543 sqlite3_vfs *pVfs,
544 const char *zName,
drh2f4d0ec2021-05-10 23:48:46 +0000545 sqlite3_file *pFd,
drhac442f42018-01-03 01:28:46 +0000546 int flags,
547 int *pOutFlags
548){
drh2f4d0ec2021-05-10 23:48:46 +0000549 MemFile *pFile = (MemFile*)pFd;
550 MemStore *p = 0;
551 int szName;
drh90385dd2021-10-27 15:19:01 +0000552 UNUSED_PARAMETER(pVfs);
drh88944e62021-10-23 17:46:00 +0000553
larrybr3a9793e2021-09-10 18:35:59 +0000554 memset(pFile, 0, sizeof(*pFile));
drh2f4d0ec2021-05-10 23:48:46 +0000555 szName = sqlite3Strlen30(zName);
dan118b53b2022-12-15 18:56:12 +0000556 if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){
drh2f4d0ec2021-05-10 23:48:46 +0000557 int i;
drh2d344f92021-05-12 02:52:20 +0000558#ifndef SQLITE_MUTEX_OMIT
drh2f4d0ec2021-05-10 23:48:46 +0000559 sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
drh2d344f92021-05-12 02:52:20 +0000560#endif
drh2f4d0ec2021-05-10 23:48:46 +0000561 sqlite3_mutex_enter(pVfsMutex);
562 for(i=0; i<memdb_g.nMemStore; i++){
563 if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
564 p = memdb_g.apMemStore[i];
565 break;
566 }
567 }
568 if( p==0 ){
569 MemStore **apNew;
570 p = sqlite3Malloc( sizeof(*p) + szName + 3 );
571 if( p==0 ){
572 sqlite3_mutex_leave(pVfsMutex);
573 return SQLITE_NOMEM;
574 }
575 apNew = sqlite3Realloc(memdb_g.apMemStore,
576 sizeof(apNew[0])*(memdb_g.nMemStore+1) );
577 if( apNew==0 ){
578 sqlite3_free(p);
579 sqlite3_mutex_leave(pVfsMutex);
580 return SQLITE_NOMEM;
581 }
582 apNew[memdb_g.nMemStore++] = p;
583 memdb_g.apMemStore = apNew;
584 memset(p, 0, sizeof(*p));
585 p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
586 p->szMax = sqlite3GlobalConfig.mxMemdbSize;
587 p->zFName = (char*)&p[1];
588 memcpy(p->zFName, zName, szName+1);
589 p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
drh2d344f92021-05-12 02:52:20 +0000590 if( p->pMutex==0 ){
591 memdb_g.nMemStore--;
592 sqlite3_free(p);
593 sqlite3_mutex_leave(pVfsMutex);
594 return SQLITE_NOMEM;
595 }
drh2f4d0ec2021-05-10 23:48:46 +0000596 p->nRef = 1;
597 memdbEnter(p);
598 }else{
599 memdbEnter(p);
600 p->nRef++;
601 }
602 sqlite3_mutex_leave(pVfsMutex);
603 }else{
604 p = sqlite3Malloc( sizeof(*p) );
605 if( p==0 ){
606 return SQLITE_NOMEM;
607 }
608 memset(p, 0, sizeof(*p));
609 p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
610 p->szMax = sqlite3GlobalConfig.mxMemdbSize;
611 }
612 pFile->pStore = p;
drh88944e62021-10-23 17:46:00 +0000613 if( pOutFlags!=0 ){
614 *pOutFlags = flags | SQLITE_OPEN_MEMORY;
615 }
drh2f4d0ec2021-05-10 23:48:46 +0000616 pFd->pMethods = &memdb_io_methods;
617 memdbLeave(p);
drhac442f42018-01-03 01:28:46 +0000618 return SQLITE_OK;
619}
620
drh067b92b2020-06-19 15:24:12 +0000621#if 0 /* Only used to delete rollback journals, super-journals, and WAL
drh14714162018-03-06 19:14:32 +0000622 ** files, none of which exist in memdb. So this routine is never used */
drhac442f42018-01-03 01:28:46 +0000623/*
624** Delete the file located at zPath. If the dirSync argument is true,
625** ensure the file-system modifications are synced to disk before
626** returning.
627*/
628static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
629 return SQLITE_IOERR_DELETE;
630}
drh14714162018-03-06 19:14:32 +0000631#endif
drhac442f42018-01-03 01:28:46 +0000632
633/*
634** Test for access permissions. Return true if the requested permission
635** is available, or false otherwise.
drh14714162018-03-06 19:14:32 +0000636**
637** With memdb, no files ever exist on disk. So always return false.
drhac442f42018-01-03 01:28:46 +0000638*/
639static int memdbAccess(
640 sqlite3_vfs *pVfs,
641 const char *zPath,
642 int flags,
643 int *pResOut
644){
drh904e48e2021-05-17 17:14:38 +0000645 UNUSED_PARAMETER(pVfs);
646 UNUSED_PARAMETER(zPath);
647 UNUSED_PARAMETER(flags);
drhac442f42018-01-03 01:28:46 +0000648 *pResOut = 0;
649 return SQLITE_OK;
650}
651
652/*
653** Populate buffer zOut with the full canonical pathname corresponding
654** to the pathname in zPath. zOut is guaranteed to point to a buffer
655** of at least (INST_MAX_PATHNAME+1) bytes.
656*/
657static int memdbFullPathname(
658 sqlite3_vfs *pVfs,
659 const char *zPath,
660 int nOut,
661 char *zOut
662){
drh904e48e2021-05-17 17:14:38 +0000663 UNUSED_PARAMETER(pVfs);
drhac442f42018-01-03 01:28:46 +0000664 sqlite3_snprintf(nOut, zOut, "%s", zPath);
665 return SQLITE_OK;
666}
667
668/*
669** Open the dynamic library located at zPath and return a handle.
670*/
671static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
672 return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
673}
674
675/*
676** Populate the buffer zErrMsg (size nByte bytes) with a human readable
677** utf-8 string describing the most recent error encountered associated
678** with dynamic libraries.
679*/
680static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
681 ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
682}
683
684/*
685** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
686*/
687static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
688 return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
689}
690
691/*
692** Close the dynamic library handle pHandle.
693*/
694static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
695 ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
696}
697
698/*
699** Populate the buffer pointed to by zBufOut with nByte bytes of
700** random data.
701*/
702static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
703 return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
704}
705
706/*
707** Sleep for nMicro microseconds. Return the number of microseconds
708** actually slept.
709*/
710static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
711 return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
712}
713
drh14714162018-03-06 19:14:32 +0000714#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
drhac442f42018-01-03 01:28:46 +0000715/*
716** Return the current time as a Julian Day number in *pTimeOut.
717*/
718static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
719 return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
720}
drh14714162018-03-06 19:14:32 +0000721#endif
drhac442f42018-01-03 01:28:46 +0000722
723static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
724 return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
725}
726static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
727 return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
728}
729
730/*
731** Translate a database connection pointer and schema name into a
732** MemFile pointer.
733*/
734static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
735 MemFile *p = 0;
drh2f4d0ec2021-05-10 23:48:46 +0000736 MemStore *pStore;
drhac442f42018-01-03 01:28:46 +0000737 int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
738 if( rc ) return 0;
739 if( p->base.pMethods!=&memdb_io_methods ) return 0;
drh2f4d0ec2021-05-10 23:48:46 +0000740 pStore = p->pStore;
741 memdbEnter(pStore);
742 if( pStore->zFName!=0 ) p = 0;
743 memdbLeave(pStore);
drhac442f42018-01-03 01:28:46 +0000744 return p;
745}
746
747/*
drhcb7d5412018-01-03 16:49:52 +0000748** Return the serialization of a database
749*/
750unsigned char *sqlite3_serialize(
751 sqlite3 *db, /* The database connection */
752 const char *zSchema, /* Which database within the connection */
753 sqlite3_int64 *piSize, /* Write size here, if not NULL */
754 unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
755){
drhb2194ce2018-03-01 22:18:26 +0000756 MemFile *p;
757 int iDb;
drhcb7d5412018-01-03 16:49:52 +0000758 Btree *pBt;
759 sqlite3_int64 sz;
760 int szPage = 0;
761 sqlite3_stmt *pStmt = 0;
762 unsigned char *pOut;
763 char *zSql;
764 int rc;
765
mistachkin6630f942018-03-08 19:56:52 +0000766#ifdef SQLITE_ENABLE_API_ARMOR
767 if( !sqlite3SafetyCheckOk(db) ){
768 (void)SQLITE_MISUSE_BKPT;
769 return 0;
770 }
771#endif
772
drhb2194ce2018-03-01 22:18:26 +0000773 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
774 p = memdbFromDbSchema(db, zSchema);
775 iDb = sqlite3FindDbName(db, zSchema);
drhcb7d5412018-01-03 16:49:52 +0000776 if( piSize ) *piSize = -1;
777 if( iDb<0 ) return 0;
778 if( p ){
drh2f4d0ec2021-05-10 23:48:46 +0000779 MemStore *pStore = p->pStore;
780 assert( pStore->pMutex==0 );
781 if( piSize ) *piSize = pStore->sz;
drhcb7d5412018-01-03 16:49:52 +0000782 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
drh2f4d0ec2021-05-10 23:48:46 +0000783 pOut = pStore->aData;
drhcb7d5412018-01-03 16:49:52 +0000784 }else{
drh2f4d0ec2021-05-10 23:48:46 +0000785 pOut = sqlite3_malloc64( pStore->sz );
786 if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
drhcb7d5412018-01-03 16:49:52 +0000787 }
788 return pOut;
789 }
790 pBt = db->aDb[iDb].pBt;
791 if( pBt==0 ) return 0;
792 szPage = sqlite3BtreeGetPageSize(pBt);
793 zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
794 rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
795 sqlite3_free(zSql);
796 if( rc ) return 0;
drh8784efa2018-03-06 20:54:27 +0000797 rc = sqlite3_step(pStmt);
798 if( rc!=SQLITE_ROW ){
drhcb7d5412018-01-03 16:49:52 +0000799 pOut = 0;
800 }else{
drh8784efa2018-03-06 20:54:27 +0000801 sz = sqlite3_column_int64(pStmt, 0)*szPage;
802 if( piSize ) *piSize = sz;
803 if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
804 pOut = 0;
805 }else{
806 pOut = sqlite3_malloc64( sz );
807 if( pOut ){
808 int nPage = sqlite3_column_int(pStmt, 0);
809 Pager *pPager = sqlite3BtreePager(pBt);
810 int pgno;
811 for(pgno=1; pgno<=nPage; pgno++){
812 DbPage *pPage = 0;
813 unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
814 rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
815 if( rc==SQLITE_OK ){
816 memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
817 }else{
818 memset(pTo, 0, szPage);
819 }
820 sqlite3PagerUnref(pPage);
drhcb7d5412018-01-03 16:49:52 +0000821 }
drhcb7d5412018-01-03 16:49:52 +0000822 }
823 }
824 }
825 sqlite3_finalize(pStmt);
826 return pOut;
827}
828
drh3ec86652018-01-03 19:03:31 +0000829/* Convert zSchema to a MemDB and initialize its content.
830*/
831int sqlite3_deserialize(
832 sqlite3 *db, /* The database connection */
833 const char *zSchema, /* Which DB to reopen with the deserialization */
834 unsigned char *pData, /* The serialized database content */
835 sqlite3_int64 szDb, /* Number bytes in the deserialization */
836 sqlite3_int64 szBuf, /* Total size of buffer pData[] */
837 unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
838){
839 MemFile *p;
840 char *zSql;
841 sqlite3_stmt *pStmt = 0;
842 int rc;
843 int iDb;
844
mistachkin6630f942018-03-08 19:56:52 +0000845#ifdef SQLITE_ENABLE_API_ARMOR
846 if( !sqlite3SafetyCheckOk(db) ){
847 return SQLITE_MISUSE_BKPT;
848 }
849 if( szDb<0 ) return SQLITE_MISUSE_BKPT;
850 if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
851#endif
852
drh3ec86652018-01-03 19:03:31 +0000853 sqlite3_mutex_enter(db->mutex);
854 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
855 iDb = sqlite3FindDbName(db, zSchema);
drh53fa0252021-07-20 02:02:24 +0000856 testcase( iDb==1 );
857 if( iDb<2 && iDb!=0 ){
drh3ec86652018-01-03 19:03:31 +0000858 rc = SQLITE_ERROR;
859 goto end_deserialize;
drh53fa0252021-07-20 02:02:24 +0000860 }
drh3ec86652018-01-03 19:03:31 +0000861 zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
drh672f07c2020-10-20 14:40:53 +0000862 if( zSql==0 ){
863 rc = SQLITE_NOMEM;
864 }else{
865 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
866 sqlite3_free(zSql);
867 }
drh3ec86652018-01-03 19:03:31 +0000868 if( rc ) goto end_deserialize;
869 db->init.iDb = (u8)iDb;
870 db->init.reopenMemdb = 1;
871 rc = sqlite3_step(pStmt);
872 db->init.reopenMemdb = 0;
873 if( rc!=SQLITE_DONE ){
874 rc = SQLITE_ERROR;
875 goto end_deserialize;
876 }
877 p = memdbFromDbSchema(db, zSchema);
drh8784efa2018-03-06 20:54:27 +0000878 if( p==0 ){
879 rc = SQLITE_ERROR;
880 }else{
drh2f4d0ec2021-05-10 23:48:46 +0000881 MemStore *pStore = p->pStore;
882 pStore->aData = pData;
drhff01ee32020-10-17 22:13:16 +0000883 pData = 0;
drh2f4d0ec2021-05-10 23:48:46 +0000884 pStore->sz = szDb;
885 pStore->szAlloc = szBuf;
886 pStore->szMax = szBuf;
887 if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
888 pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
drh6ca64482019-01-22 16:06:20 +0000889 }
drh2f4d0ec2021-05-10 23:48:46 +0000890 pStore->mFlags = mFlags;
drh8784efa2018-03-06 20:54:27 +0000891 rc = SQLITE_OK;
892 }
893
drh3ec86652018-01-03 19:03:31 +0000894end_deserialize:
895 sqlite3_finalize(pStmt);
drhff01ee32020-10-17 22:13:16 +0000896 if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
897 sqlite3_free(pData);
898 }
drh3ec86652018-01-03 19:03:31 +0000899 sqlite3_mutex_leave(db->mutex);
900 return rc;
901}
902
drhcf3107c2022-11-19 00:08:35 +0000903/*
904** Return true if the VFS is the memvfs.
905*/
906int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
907 return pVfs==&memdb_vfs;
908}
909
drhac442f42018-01-03 01:28:46 +0000910/*
911** This routine is called when the extension is loaded.
912** Register the new VFS.
913*/
914int sqlite3MemdbInit(void){
drh5f9d1922018-03-06 04:01:08 +0000915 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000916 unsigned int sz;
917 if( NEVER(pLower==0) ) return SQLITE_ERROR;
918 sz = pLower->szOsFile;
drh5f9d1922018-03-06 04:01:08 +0000919 memdb_vfs.pAppData = pLower;
drhf25f8d52020-05-21 20:38:39 +0000920 /* The following conditional can only be true when compiled for
921 ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
922 ** it in, to be safe, but it is marked as NO_TEST since there
923 ** is no way to reach it under most builds. */
924 if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
drh5f9d1922018-03-06 04:01:08 +0000925 memdb_vfs.szOsFile = sz;
drhac442f42018-01-03 01:28:46 +0000926 return sqlite3_vfs_register(&memdb_vfs, 0);
927}
drh8d889af2021-05-08 17:18:23 +0000928#endif /* SQLITE_OMIT_DESERIALIZE */