/ Check-in [fb2ac2d2]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for the "memdb" VFS and the sqlite3_memdb_ptr() and sqlite3_memdb_config() interfaces, to enable an SQLite database to be manipulated as an in-memory object.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | memdb
Files: files | file ages | folders
SHA3-256: fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a
User & Date: drh 2018-01-03 01:28:46
Context
2018-01-03
12:39
Fix typo in the Makefile for MSVC. check-in: e5c6ade8 user: mistachkin tags: memdb
01:28
Add support for the "memdb" VFS and the sqlite3_memdb_ptr() and sqlite3_memdb_config() interfaces, to enable an SQLite database to be manipulated as an in-memory object. check-in: fb2ac2d2 user: drh tags: memdb
2018-01-02
21:29
Fix code indentation. No logic changes. check-in: e115f258 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   176    176            fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
   177    177            fts3_tokenize_vtab.lo \
   178    178            fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
   179    179   	 fts5.lo \
   180    180            func.lo global.lo hash.lo \
   181    181            icu.lo insert.lo json1.lo legacy.lo loadext.lo \
   182    182            main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   183         -         memjournal.lo \
          183  +         memdb.lo memjournal.lo \
   184    184            mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
   185    185            notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
   186    186            pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
   187    187            random.lo resolve.lo rowset.lo rtree.lo \
   188    188            sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
   189    189            table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
   190    190            update.lo util.lo vacuum.lo \
................................................................................
   236    236     $(TOP)/src/main.c \
   237    237     $(TOP)/src/malloc.c \
   238    238     $(TOP)/src/mem0.c \
   239    239     $(TOP)/src/mem1.c \
   240    240     $(TOP)/src/mem2.c \
   241    241     $(TOP)/src/mem3.c \
   242    242     $(TOP)/src/mem5.c \
          243  +  $(TOP)/src/memdb.c \
   243    244     $(TOP)/src/memjournal.c \
   244    245     $(TOP)/src/msvc.h \
   245    246     $(TOP)/src/mutex.c \
   246    247     $(TOP)/src/mutex.h \
   247    248     $(TOP)/src/mutex_noop.c \
   248    249     $(TOP)/src/mutex_unix.c \
   249    250     $(TOP)/src/mutex_w32.c \
................................................................................
   820    821   
   821    822   mem3.lo:	$(TOP)/src/mem3.c $(HDR)
   822    823   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c
   823    824   
   824    825   mem5.lo:	$(TOP)/src/mem5.c $(HDR)
   825    826   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c
   826    827   
          828  +memdb.lo:	$(TOP)/src/memdb.c $(HDR)
          829  +	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memdb.c
          830  +
   827    831   memjournal.lo:	$(TOP)/src/memjournal.c $(HDR)
   828    832   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memjournal.c
   829    833   
   830    834   mutex.lo:	$(TOP)/src/mutex.c $(HDR)
   831    835   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c
   832    836   
   833    837   mutex_noop.lo:	$(TOP)/src/mutex_noop.c $(HDR)

Changes to Makefile.msc.

  1097   1097            fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
  1098   1098            fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
  1099   1099            fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
  1100   1100            fts5.lo \
  1101   1101            func.lo global.lo hash.lo \
  1102   1102            icu.lo insert.lo legacy.lo loadext.lo \
  1103   1103            main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
  1104         -         memjournal.lo \
         1104  +         memdb.lo memjournal.lo \
  1105   1105            mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
  1106   1106            notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
  1107   1107            pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
  1108   1108            random.lo resolve.lo rowset.lo rtree.lo \
  1109   1109            sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
  1110   1110            table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
  1111   1111            update.lo util.lo vacuum.lo \
................................................................................
  1170   1170     $(TOP)\src\main.c \
  1171   1171     $(TOP)\src\malloc.c \
  1172   1172     $(TOP)\src\mem0.c \
  1173   1173     $(TOP)\src\mem1.c \
  1174   1174     $(TOP)\src\mem2.c \
  1175   1175     $(TOP)\src\mem3.c \
  1176   1176     $(TOP)\src\mem5.c \
         1177  +  $(TOP)\src\memdb.c \
  1177   1178     $(TOP)\src\memjournal.c \
  1178   1179     $(TOP)\src\mutex.c \
  1179   1180     $(TOP)\src\mutex_noop.c \
  1180   1181     $(TOP)\src\mutex_unix.c \
  1181   1182     $(TOP)\src\mutex_w32.c \
  1182   1183     $(TOP)\src\notify.c \
  1183   1184     $(TOP)\src\os.c \
................................................................................
  1803   1804   
  1804   1805   mem3.lo:	$(TOP)\src\mem3.c $(HDR)
  1805   1806   	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem3.c
  1806   1807   
  1807   1808   mem5.lo:	$(TOP)\src\mem5.c $(HDR)
  1808   1809   	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c
  1809   1810   
         1811  +memdb.lo:	$(TOP)\src\memjournal.c $(HDR)
         1812  +	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c
         1813  +
  1810   1814   memjournal.lo:	$(TOP)\src\memjournal.c $(HDR)
  1811   1815   	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c
  1812   1816   
  1813   1817   mutex.lo:	$(TOP)\src\mutex.c $(HDR)
  1814   1818   	$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex.c
  1815   1819   
  1816   1820   mutex_noop.lo:	$(TOP)\src\mutex_noop.c $(HDR)

Changes to main.mk.

    61     61            fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
    62     62            fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
    63     63            fts3_tokenize_vtab.o \
    64     64   	 fts3_unicode.o fts3_unicode2.o \
    65     65            fts3_write.o fts5.o func.o global.o hash.o \
    66     66            icu.o insert.o json1.o legacy.o loadext.o \
    67     67            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    68         -         memjournal.o \
           68  +         memdb.o memjournal.o \
    69     69            mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
    70     70            notify.o opcodes.o os.o os_unix.o os_win.o \
    71     71            pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    72     72            random.o resolve.o rowset.o rtree.o \
    73     73            select.o sqlite3rbu.o status.o stmt.o \
    74     74            table.o threads.o tokenize.o treeview.o trigger.o \
    75     75            update.o userauth.o util.o vacuum.o \
................................................................................
   114    114     $(TOP)/src/main.c \
   115    115     $(TOP)/src/malloc.c \
   116    116     $(TOP)/src/mem0.c \
   117    117     $(TOP)/src/mem1.c \
   118    118     $(TOP)/src/mem2.c \
   119    119     $(TOP)/src/mem3.c \
   120    120     $(TOP)/src/mem5.c \
          121  +  $(TOP)/src/memdb.c \
   121    122     $(TOP)/src/memjournal.c \
   122    123     $(TOP)/src/msvc.h \
   123    124     $(TOP)/src/mutex.c \
   124    125     $(TOP)/src/mutex.h \
   125    126     $(TOP)/src/mutex_noop.c \
   126    127     $(TOP)/src/mutex_unix.c \
   127    128     $(TOP)/src/mutex_w32.c \

Changes to src/main.c.

   235    235       if( sqlite3GlobalConfig.isPCacheInit==0 ){
   236    236         rc = sqlite3PcacheInitialize();
   237    237       }
   238    238       if( rc==SQLITE_OK ){
   239    239         sqlite3GlobalConfig.isPCacheInit = 1;
   240    240         rc = sqlite3OsInit();
   241    241       }
          242  +#ifdef SQLITE_ENABLE_MEMDB
          243  +    if( rc==SQLITE_OK ){
          244  +      rc = sqlite3MemdbInit();
          245  +    }
          246  +#endif
   242    247       if( rc==SQLITE_OK ){
   243    248         sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
   244    249             sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
   245    250         sqlite3GlobalConfig.isInit = 1;
   246    251   #ifdef SQLITE_EXTRA_INIT
   247    252         bRunExtraInit = 1;
   248    253   #endif
................................................................................
   267    272     ** been compiled correctly.  It is important to run this code, but
   268    273     ** we don't want to run it too often and soak up CPU cycles for no
   269    274     ** reason.  So we run it once during initialization.
   270    275     */
   271    276   #ifndef NDEBUG
   272    277   #ifndef SQLITE_OMIT_FLOATING_POINT
   273    278     /* This section of code's only "output" is via assert() statements. */
   274         -  if ( rc==SQLITE_OK ){
          279  +  if( rc==SQLITE_OK ){
   275    280       u64 x = (((u64)1)<<63)-1;
   276    281       double y;
   277    282       assert(sizeof(x)==8);
   278    283       assert(sizeof(x)==sizeof(y));
   279    284       memcpy(&y, &x, 8);
   280    285       assert( sqlite3IsNaN(y) );
   281    286     }

Added src/memdb.c.

            1  +/*
            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  +**
           13  +** This is an in-memory VFS implementation.  The application supplies
           14  +** a chunk of memory to hold the database file.
           15  +**
           16  +** USAGE:
           17  +**
           18  +**    sqlite3_open_v2("whatever", &db, SQLITE_OPEN_READWRITE, "memdb");
           19  +**    void *sqlite3_memdb_ptr(db, "main", &sz);
           20  +**    int sqlite3_memdb_config(db, "main", pMem, szData, szMem, mFlags);
           21  +**
           22  +** Flags:
           23  +**
           24  +**    SQLITE_MEMDB_FREEONCLOSE        Free pMem when closing the connection
           25  +**    SQLITE_MEMDB_RESIZEABLE         Use sqlite3_realloc64() to resize pMem
           26  +*/
           27  +#ifdef SQLITE_ENABLE_MEMDB
           28  +#include "sqliteInt.h"
           29  +
           30  +/*
           31  +** Forward declaration of objects used by this utility
           32  +*/
           33  +typedef struct sqlite3_vfs MemVfs;
           34  +typedef struct MemFile MemFile;
           35  +
           36  +/* Access to a lower-level VFS that (might) implement dynamic loading,
           37  +** access to randomness, etc.
           38  +*/
           39  +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
           40  +
           41  +/* An open file */
           42  +struct MemFile {
           43  +  sqlite3_file base;              /* IO methods */
           44  +  sqlite3_int64 sz;               /* Size of the file */
           45  +  sqlite3_int64 szMax;            /* Space allocated to aData */
           46  +  unsigned char *aData;           /* content of the file */
           47  +  int nMmap;                      /* Number of memory mapped pages */
           48  +  unsigned mFlags;                /* Flags */
           49  +  int eLock;                      /* Most recent lock against this file */
           50  +};
           51  +
           52  +/*
           53  +** Methods for MemFile
           54  +*/
           55  +static int memdbClose(sqlite3_file*);
           56  +static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
           57  +static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
           58  +static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
           59  +static int memdbSync(sqlite3_file*, int flags);
           60  +static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
           61  +static int memdbLock(sqlite3_file*, int);
           62  +static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);
           63  +static int memdbFileControl(sqlite3_file*, int op, void *pArg);
           64  +static int memdbSectorSize(sqlite3_file*);
           65  +static int memdbDeviceCharacteristics(sqlite3_file*);
           66  +static int memdbShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
           67  +static int memdbShmLock(sqlite3_file*, int offset, int n, int flags);
           68  +static void memdbShmBarrier(sqlite3_file*);
           69  +static int memdbShmUnmap(sqlite3_file*, int deleteFlag);
           70  +static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
           71  +static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
           72  +
           73  +/*
           74  +** Methods for MemVfs
           75  +*/
           76  +static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
           77  +static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir);
           78  +static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
           79  +static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
           80  +static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
           81  +static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
           82  +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
           83  +static void memdbDlClose(sqlite3_vfs*, void*);
           84  +static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
           85  +static int memdbSleep(sqlite3_vfs*, int microseconds);
           86  +static int memdbCurrentTime(sqlite3_vfs*, double*);
           87  +static int memdbGetLastError(sqlite3_vfs*, int, char *);
           88  +static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
           89  +
           90  +static sqlite3_vfs memdb_vfs = {
           91  +  2,                           /* iVersion */
           92  +  0,                           /* szOsFile (set when registered) */
           93  +  1024,                        /* mxPathname */
           94  +  0,                           /* pNext */
           95  +  "memdb",                     /* zName */
           96  +  0,                           /* pAppData (set when registered) */ 
           97  +  memdbOpen,                   /* xOpen */
           98  +  memdbDelete,                 /* xDelete */
           99  +  memdbAccess,                 /* xAccess */
          100  +  memdbFullPathname,           /* xFullPathname */
          101  +  memdbDlOpen,                 /* xDlOpen */
          102  +  memdbDlError,                /* xDlError */
          103  +  memdbDlSym,                  /* xDlSym */
          104  +  memdbDlClose,                /* xDlClose */
          105  +  memdbRandomness,             /* xRandomness */
          106  +  memdbSleep,                  /* xSleep */
          107  +  memdbCurrentTime,            /* xCurrentTime */
          108  +  memdbGetLastError,           /* xGetLastError */
          109  +  memdbCurrentTimeInt64        /* xCurrentTimeInt64 */
          110  +};
          111  +
          112  +static const sqlite3_io_methods memdb_io_methods = {
          113  +  3,                              /* iVersion */
          114  +  memdbClose,                      /* xClose */
          115  +  memdbRead,                       /* xRead */
          116  +  memdbWrite,                      /* xWrite */
          117  +  memdbTruncate,                   /* xTruncate */
          118  +  memdbSync,                       /* xSync */
          119  +  memdbFileSize,                   /* xFileSize */
          120  +  memdbLock,                       /* xLock */
          121  +  memdbLock,                       /* xUnlock - same as xLock in this case */ 
          122  +  memdbCheckReservedLock,          /* xCheckReservedLock */
          123  +  memdbFileControl,                /* xFileControl */
          124  +  memdbSectorSize,                 /* xSectorSize */
          125  +  memdbDeviceCharacteristics,      /* xDeviceCharacteristics */
          126  +  memdbShmMap,                     /* xShmMap */
          127  +  memdbShmLock,                    /* xShmLock */
          128  +  memdbShmBarrier,                 /* xShmBarrier */
          129  +  memdbShmUnmap,                   /* xShmUnmap */
          130  +  memdbFetch,                      /* xFetch */
          131  +  memdbUnfetch                     /* xUnfetch */
          132  +};
          133  +
          134  +
          135  +
          136  +/*
          137  +** Close an memdb-file.
          138  +**
          139  +** The pData pointer is owned by the application, so there is nothing
          140  +** to free.
          141  +*/
          142  +static int memdbClose(sqlite3_file *pFile){
          143  +  MemFile *p = (MemFile *)pFile;
          144  +  if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData);
          145  +  return SQLITE_OK;
          146  +}
          147  +
          148  +/*
          149  +** Read data from an memdb-file.
          150  +*/
          151  +static int memdbRead(
          152  +  sqlite3_file *pFile, 
          153  +  void *zBuf, 
          154  +  int iAmt, 
          155  +  sqlite_int64 iOfst
          156  +){
          157  +  MemFile *p = (MemFile *)pFile;
          158  +  if( iOfst+iAmt>p->sz ){
          159  +    memset(zBuf, 0, iAmt);
          160  +    return SQLITE_IOERR_SHORT_READ;
          161  +  }
          162  +  memcpy(zBuf, p->aData+iOfst, iAmt);
          163  +  return SQLITE_OK;
          164  +}
          165  +
          166  +/*
          167  +** Try to enlarge the memory allocation to hold at least sz bytes
          168  +*/
          169  +static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
          170  +  unsigned char *pNew;
          171  +  if( (p->mFlags & SQLITE_MEMDB_RESIZEABLE)==0 ) return SQLITE_FULL;
          172  +  if( p->nMmap>0 ) return SQLITE_FULL;
          173  +  pNew = sqlite3_realloc64(p->aData, newSz);
          174  +  if( pNew==0 ) return SQLITE_FULL;
          175  +  p->aData = pNew;
          176  +  p->szMax = newSz;
          177  +  return SQLITE_OK;
          178  +}
          179  +
          180  +/*
          181  +** Write data to an memdb-file.
          182  +*/
          183  +static int memdbWrite(
          184  +  sqlite3_file *pFile,
          185  +  const void *z,
          186  +  int iAmt,
          187  +  sqlite_int64 iOfst
          188  +){
          189  +  MemFile *p = (MemFile *)pFile;
          190  +  if( iOfst+iAmt>p->sz ){
          191  +    if( iOfst+iAmt>p->szMax && memdbEnlarge(p, (iOfst+iAmt)*2) ){
          192  +      return SQLITE_FULL;
          193  +    }
          194  +    if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
          195  +    p->sz = iOfst+iAmt;
          196  +  }
          197  +  memcpy(p->aData+iOfst, z, iAmt);
          198  +  return SQLITE_OK;
          199  +}
          200  +
          201  +/*
          202  +** Truncate an memdb-file.
          203  +*/
          204  +static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
          205  +  MemFile *p = (MemFile *)pFile;
          206  +  if( size>p->sz ){
          207  +    if( size>p->szMax && memdbEnlarge(p, size) ) return SQLITE_FULL;
          208  +    memset(p->aData+p->sz, 0, size-p->sz);
          209  +  }
          210  +  p->sz = size; 
          211  +  return SQLITE_OK;
          212  +}
          213  +
          214  +/*
          215  +** Sync an memdb-file.
          216  +*/
          217  +static int memdbSync(sqlite3_file *pFile, int flags){
          218  +  return SQLITE_OK;
          219  +}
          220  +
          221  +/*
          222  +** Return the current file-size of an memdb-file.
          223  +*/
          224  +static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
          225  +  MemFile *p = (MemFile *)pFile;
          226  +  *pSize = p->sz;
          227  +  return SQLITE_OK;
          228  +}
          229  +
          230  +/*
          231  +** Lock an memdb-file.
          232  +*/
          233  +static int memdbLock(sqlite3_file *pFile, int eLock){
          234  +  MemFile *p = (MemFile *)pFile;
          235  +  p->eLock = eLock;
          236  +  return SQLITE_OK;
          237  +}
          238  +
          239  +/*
          240  +** Check if another file-handle holds a RESERVED lock on an memdb-file.
          241  +*/
          242  +static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
          243  +  *pResOut = 0;
          244  +  return SQLITE_OK;
          245  +}
          246  +
          247  +/*
          248  +** File control method. For custom operations on an memdb-file.
          249  +*/
          250  +static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
          251  +  MemFile *p = (MemFile *)pFile;
          252  +  int rc = SQLITE_NOTFOUND;
          253  +  if( op==SQLITE_FCNTL_VFSNAME ){
          254  +    *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
          255  +    rc = SQLITE_OK;
          256  +  }
          257  +  return rc;
          258  +}
          259  +
          260  +/*
          261  +** Return the sector-size in bytes for an memdb-file.
          262  +*/
          263  +static int memdbSectorSize(sqlite3_file *pFile){
          264  +  return 1024;
          265  +}
          266  +
          267  +/*
          268  +** Return the device characteristic flags supported by an memdb-file.
          269  +*/
          270  +static int memdbDeviceCharacteristics(sqlite3_file *pFile){
          271  +  return SQLITE_IOCAP_ATOMIC | 
          272  +         SQLITE_IOCAP_POWERSAFE_OVERWRITE |
          273  +         SQLITE_IOCAP_SAFE_APPEND |
          274  +         SQLITE_IOCAP_SEQUENTIAL;
          275  +}
          276  +
          277  +/* Create a shared memory file mapping */
          278  +static int memdbShmMap(
          279  +  sqlite3_file *pFile,
          280  +  int iPg,
          281  +  int pgsz,
          282  +  int bExtend,
          283  +  void volatile **pp
          284  +){
          285  +  return SQLITE_IOERR_SHMMAP;
          286  +}
          287  +
          288  +/* Perform locking on a shared-memory segment */
          289  +static int memdbShmLock(sqlite3_file *pFile, int offset, int n, int flags){
          290  +  return SQLITE_IOERR_SHMLOCK;
          291  +}
          292  +
          293  +/* Memory barrier operation on shared memory */
          294  +static void memdbShmBarrier(sqlite3_file *pFile){
          295  +  return;
          296  +}
          297  +
          298  +/* Unmap a shared memory segment */
          299  +static int memdbShmUnmap(sqlite3_file *pFile, int deleteFlag){
          300  +  return SQLITE_OK;
          301  +}
          302  +
          303  +/* Fetch a page of a memory-mapped file */
          304  +static int memdbFetch(
          305  +  sqlite3_file *pFile,
          306  +  sqlite3_int64 iOfst,
          307  +  int iAmt,
          308  +  void **pp
          309  +){
          310  +  MemFile *p = (MemFile *)pFile;
          311  +  p->nMmap++;
          312  +  *pp = (void*)(p->aData + iOfst);
          313  +  return SQLITE_OK;
          314  +}
          315  +
          316  +/* Release a memory-mapped page */
          317  +static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
          318  +  MemFile *p = (MemFile *)pFile;
          319  +  p->nMmap--;
          320  +  return SQLITE_OK;
          321  +}
          322  +
          323  +/*
          324  +** Open an mem file handle.
          325  +*/
          326  +static int memdbOpen(
          327  +  sqlite3_vfs *pVfs,
          328  +  const char *zName,
          329  +  sqlite3_file *pFile,
          330  +  int flags,
          331  +  int *pOutFlags
          332  +){
          333  +  MemFile *p = (MemFile*)pFile;
          334  +  memset(p, 0, sizeof(*p));
          335  +  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN;
          336  +  p->mFlags = SQLITE_MEMDB_RESIZEABLE | SQLITE_MEMDB_FREEONCLOSE;
          337  +  *pOutFlags = flags | SQLITE_OPEN_MEMORY;
          338  +  p->base.pMethods = &memdb_io_methods;
          339  +  return SQLITE_OK;
          340  +}
          341  +
          342  +/*
          343  +** Delete the file located at zPath. If the dirSync argument is true,
          344  +** ensure the file-system modifications are synced to disk before
          345  +** returning.
          346  +*/
          347  +static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
          348  +  return SQLITE_IOERR_DELETE;
          349  +}
          350  +
          351  +/*
          352  +** Test for access permissions. Return true if the requested permission
          353  +** is available, or false otherwise.
          354  +*/
          355  +static int memdbAccess(
          356  +  sqlite3_vfs *pVfs, 
          357  +  const char *zPath, 
          358  +  int flags, 
          359  +  int *pResOut
          360  +){
          361  +  *pResOut = 0;
          362  +  return SQLITE_OK;
          363  +}
          364  +
          365  +/*
          366  +** Populate buffer zOut with the full canonical pathname corresponding
          367  +** to the pathname in zPath. zOut is guaranteed to point to a buffer
          368  +** of at least (INST_MAX_PATHNAME+1) bytes.
          369  +*/
          370  +static int memdbFullPathname(
          371  +  sqlite3_vfs *pVfs, 
          372  +  const char *zPath, 
          373  +  int nOut, 
          374  +  char *zOut
          375  +){
          376  +  sqlite3_snprintf(nOut, zOut, "%s", zPath);
          377  +  return SQLITE_OK;
          378  +}
          379  +
          380  +/*
          381  +** Open the dynamic library located at zPath and return a handle.
          382  +*/
          383  +static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
          384  +  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
          385  +}
          386  +
          387  +/*
          388  +** Populate the buffer zErrMsg (size nByte bytes) with a human readable
          389  +** utf-8 string describing the most recent error encountered associated 
          390  +** with dynamic libraries.
          391  +*/
          392  +static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
          393  +  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
          394  +}
          395  +
          396  +/*
          397  +** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
          398  +*/
          399  +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
          400  +  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
          401  +}
          402  +
          403  +/*
          404  +** Close the dynamic library handle pHandle.
          405  +*/
          406  +static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
          407  +  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
          408  +}
          409  +
          410  +/*
          411  +** Populate the buffer pointed to by zBufOut with nByte bytes of 
          412  +** random data.
          413  +*/
          414  +static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
          415  +  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
          416  +}
          417  +
          418  +/*
          419  +** Sleep for nMicro microseconds. Return the number of microseconds 
          420  +** actually slept.
          421  +*/
          422  +static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
          423  +  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
          424  +}
          425  +
          426  +/*
          427  +** Return the current time as a Julian Day number in *pTimeOut.
          428  +*/
          429  +static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
          430  +  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
          431  +}
          432  +
          433  +static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
          434  +  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
          435  +}
          436  +static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
          437  +  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
          438  +}
          439  +
          440  +/*
          441  +** Translate a database connection pointer and schema name into a
          442  +** MemFile pointer.
          443  +*/
          444  +static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
          445  +  MemFile *p = 0;
          446  +  int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
          447  +  if( rc ) return 0;
          448  +  if( p->base.pMethods!=&memdb_io_methods ) return 0;
          449  +  return p;
          450  +}
          451  +
          452  +/*
          453  +** Return a pointer to the memory used to hold the database.
          454  +** Return NULL if the arguments do not describe a memdb database.
          455  +*/
          456  +void *sqlite3_memdb_ptr(sqlite3 *db, const char *zSchema, sqlite3_int64 *pSz){
          457  +  MemFile *p = memdbFromDbSchema(db, zSchema);
          458  +  if( p==0 ){
          459  +    *pSz = 0;
          460  +    return 0;
          461  +  }
          462  +  *pSz = p->sz;
          463  +  return p->aData;
          464  +}
          465  +
          466  +/*
          467  +** Reconfigure a memdb database.
          468  +*/
          469  +int sqlite3_memdb_config(
          470  +  sqlite3 *db,
          471  +  const char *zSchema,
          472  +  void *aData,
          473  +  sqlite3_int64 sz,
          474  +  sqlite3_int64 szMax,
          475  +  unsigned int mFlags
          476  +){
          477  +  MemFile *p = memdbFromDbSchema(db, zSchema);
          478  +  if( p==0 ) return SQLITE_ERROR;
          479  +  if( p->eLock!=SQLITE_LOCK_NONE || p->nMmap>0 ) return SQLITE_BUSY;
          480  +  if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData);
          481  +  p->aData = aData;
          482  +  p->sz = sz;
          483  +  p->szMax = szMax;
          484  +  p->mFlags = mFlags;
          485  +  return SQLITE_OK;
          486  +}
          487  +
          488  +/* 
          489  +** This routine is called when the extension is loaded.
          490  +** Register the new VFS.
          491  +*/
          492  +int sqlite3MemdbInit(void){
          493  +  memdb_vfs.pAppData = sqlite3_vfs_find(0);
          494  +  memdb_vfs.szOsFile = sizeof(MemFile);
          495  +  return sqlite3_vfs_register(&memdb_vfs, 0);
          496  +}
          497  +#endif /* SQLITE_ENABLE_MEMDB */

Changes to src/pager.c.

  4690   4690     void (*xReinit)(DbPage*) /* Function to reinitialize pages */
  4691   4691   ){
  4692   4692     u8 *pPtr;
  4693   4693     Pager *pPager = 0;       /* Pager object to allocate and return */
  4694   4694     int rc = SQLITE_OK;      /* Return code */
  4695   4695     int tempFile = 0;        /* True for temp files (incl. in-memory files) */
  4696   4696     int memDb = 0;           /* True if this is an in-memory file */
         4697  +  int memJM = 0;           /* Memory journal mode */
  4697   4698     int readOnly = 0;        /* True if this is a read-only file */
  4698   4699     int journalFileSize;     /* Bytes to allocate for each journal fd */
  4699   4700     char *zPathname = 0;     /* Full path to database file */
  4700   4701     int nPathname = 0;       /* Number of bytes in zPathname */
  4701   4702     int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  4702   4703     int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  4703   4704     u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
................................................................................
  4817   4818   
  4818   4819     /* Open the pager file.
  4819   4820     */
  4820   4821     if( zFilename && zFilename[0] ){
  4821   4822       int fout = 0;                    /* VFS flags returned by xOpen() */
  4822   4823       rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
  4823   4824       assert( !memDb );
  4824         -    readOnly = (fout&SQLITE_OPEN_READONLY);
         4825  +    memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
         4826  +    readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
  4825   4827   
  4826   4828       /* If the file was successfully opened for read/write access,
  4827   4829       ** choose a default page size in case we have to create the
  4828   4830       ** database file. The default page size is the maximum of:
  4829   4831       **
  4830   4832       **    + SQLITE_DEFAULT_PAGE_SIZE,
  4831   4833       **    + The value returned by sqlite3OsSectorSize()
................................................................................
  4948   4950     /* pPager->pLast = 0; */
  4949   4951     pPager->nExtra = (u16)nExtra;
  4950   4952     pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
  4951   4953     assert( isOpen(pPager->fd) || tempFile );
  4952   4954     setSectorSize(pPager);
  4953   4955     if( !useJournal ){
  4954   4956       pPager->journalMode = PAGER_JOURNALMODE_OFF;
  4955         -  }else if( memDb ){
         4957  +  }else if( memDb || memJM ){
  4956   4958       pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
  4957   4959     }
  4958   4960     /* pPager->xBusyHandler = 0; */
  4959   4961     /* pPager->pBusyHandlerArg = 0; */
  4960   4962     pPager->xReiniter = xReinit;
  4961   4963     setGetterMethod(pPager);
  4962   4964     /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */

Changes to src/sqlite.h.in.

  8753   8753   ** sqlite3_snapshot_open(). It is an error if there is already a read
  8754   8754   ** transaction open on the database, or if the database is not a wal mode
  8755   8755   ** database.
  8756   8756   **
  8757   8757   ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
  8758   8758   */
  8759   8759   SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
         8760  +
         8761  +/*
         8762  +** CAPI3REF: Retrieve the current MEMDB buffer
         8763  +** EXPERIMENTAL
         8764  +**
         8765  +** This interface is only available when SQLite is compiled
         8766  +** with SQLITE_ENABLE_MEMDB.
         8767  +**
         8768  +** The sqlite3_memdb_ptr(D,S,P) interface returns a pointer to the
         8769  +** memory buffer that is the database file used for [database connection] D
         8770  +** and schema S.  If schema S of database connection D is not a MEMDB
         8771  +** database, then this routine returns NULL.  If P is not NULL, then it must
         8772  +** be a pointer to a 64-bit signed integer into which the size of the 
         8773  +** database file is written.
         8774  +*/
         8775  +SQLITE_EXPERIMENTAL void *sqlite3_memdb_ptr(sqlite3*,const char*,sqlite3_int64*);
         8776  +
         8777  +/*
         8778  +** CAPI3REF: Set the current MEMDB buffer
         8779  +** EXPERIMENTAL
         8780  +**
         8781  +** This interface is only available when SQLite is compiled
         8782  +** with SQLITE_ENABLE_MEMDB.
         8783  +**
         8784  +** The sqlite3_memdb_config(D,S,P,N,M,F) interface initializes a MEMDB database.
         8785  +** The database identified by D and S must not be in active use when this
         8786  +** interface is called, or [SQLITE_BUSY] is returned.
         8787  +*/
         8788  +SQLITE_EXPERIMENTAL int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_int64,sqlite3_int64,unsigned);
         8789  +
         8790  +/*
         8791  +** CAPI3REF: Flags for configuring MEMDB databases
         8792  +** EXPERIMENTAL
         8793  +**
         8794  +** The following are allowed values for the 6th argument (the "flags"
         8795  +** argument) of the [sqlite3_memdb_config()] interface.
         8796  +*/
         8797  +#define SQLITE_MEMDB_FREEONCLOSE  0x001   /* Free the memory buffer on close */
         8798  +#define SQLITE_MEMDB_RESIZEABLE   0x002   /* Resize using sqlite3_realloc64() */
         8799  +
  8760   8800   
  8761   8801   /*
  8762   8802   ** Undo the hack that converts floating point types to integer for
  8763   8803   ** builds on processors without floating point support.
  8764   8804   */
  8765   8805   #ifdef SQLITE_OMIT_FLOATING_POINT
  8766   8806   # undef double
  8767   8807   #endif
  8768   8808   
  8769   8809   #ifdef __cplusplus
  8770   8810   }  /* End of the 'extern "C"' block */
  8771   8811   #endif
  8772   8812   #endif /* SQLITE3_H */

Changes to src/sqliteInt.h.

  4014   4014   void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
  4015   4015   u8 sqlite3HexToInt(int h);
  4016   4016   int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
  4017   4017   
  4018   4018   #if defined(SQLITE_NEED_ERR_NAME)
  4019   4019   const char *sqlite3ErrName(int);
  4020   4020   #endif
         4021  +
         4022  +#ifdef SQLITE_ENABLE_MEMDB
         4023  +int sqlite3MemdbInit(void);
         4024  +#endif
  4021   4025   
  4022   4026   const char *sqlite3ErrStr(int);
  4023   4027   int sqlite3ReadSchema(Parse *pParse);
  4024   4028   CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
  4025   4029   CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
  4026   4030   CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
  4027   4031   CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);

Changes to src/tclsqlite.c.

  1848   1848     static const char *DB_strs[] = {
  1849   1849       "authorizer",         "backup",            "busy",
  1850   1850       "cache",              "changes",           "close",
  1851   1851       "collate",            "collation_needed",  "commit_hook",
  1852   1852       "complete",           "copy",              "enable_load_extension",
  1853   1853       "errorcode",          "eval",              "exists",
  1854   1854       "function",           "incrblob",          "interrupt",
  1855         -    "last_insert_rowid",  "nullvalue",         "onecolumn",
  1856         -    "preupdate",          "profile",           "progress",
  1857         -    "rekey",              "restore",           "rollback_hook",
  1858         -    "status",             "timeout",           "total_changes",
  1859         -    "trace",              "trace_v2",          "transaction",
  1860         -    "unlock_notify",      "update_hook",       "version",
  1861         -    "wal_hook",
  1862         -    0
         1855  +    "last_insert_rowid",  "memdb",             "nullvalue",
         1856  +    "onecolumn",          "preupdate",         "profile",
         1857  +    "progress",           "rekey",             "restore",
         1858  +    "rollback_hook",      "status",            "timeout",
         1859  +    "total_changes",      "trace",             "trace_v",
         1860  +    "transaction",        "unlock_notify",     "update_hook",
         1861  +    "version",            "wal_hook",          0
  1863   1862     };
  1864   1863     enum DB_enum {
  1865   1864       DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY,
  1866   1865       DB_CACHE,             DB_CHANGES,          DB_CLOSE,
  1867   1866       DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
  1868   1867       DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION,
  1869   1868       DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,
  1870   1869       DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT,
  1871         -    DB_LAST_INSERT_ROWID, DB_NULLVALUE,        DB_ONECOLUMN,
  1872         -    DB_PREUPDATE,         DB_PROFILE,          DB_PROGRESS,
  1873         -    DB_REKEY,             DB_RESTORE,          DB_ROLLBACK_HOOK,
  1874         -    DB_STATUS,            DB_TIMEOUT,          DB_TOTAL_CHANGES,
  1875         -    DB_TRACE,             DB_TRACE_V2,         DB_TRANSACTION,
  1876         -    DB_UNLOCK_NOTIFY,     DB_UPDATE_HOOK,      DB_VERSION,
  1877         -    DB_WAL_HOOK,
         1870  +    DB_LAST_INSERT_ROWID, DB_MEMDB,            DB_NULLVALUE,
         1871  +    DB_ONECOLUMN,         DB_PREUPDATE,        DB_PROFILE,
         1872  +    DB_PROGRESS,          DB_REKEY,            DB_RESTORE,
         1873  +    DB_ROLLBACK_HOOK,     DB_STATUS,           DB_TIMEOUT,
         1874  +    DB_TOTAL_CHANGES,     DB_TRACE,            DB_TRACE_V2,
         1875  +    DB_TRANSACTION,       DB_UNLOCK_NOTIFY,    DB_UPDATE_HOOK,
         1876  +    DB_VERSION,           DB_WAL_HOOK
  1878   1877     };
  1879   1878     /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
  1880   1879   
  1881   1880     if( objc<2 ){
  1882   1881       Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
  1883   1882       return TCL_ERROR;
  1884   1883     }
................................................................................
  2662   2661     ** Interrupt the execution of the inner-most SQL interpreter.  This
  2663   2662     ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
  2664   2663     */
  2665   2664     case DB_INTERRUPT: {
  2666   2665       sqlite3_interrupt(pDb->db);
  2667   2666       break;
  2668   2667     }
         2668  +
         2669  +  /*
         2670  +  **     $db memdb DATABASE ?BLOB?
         2671  +  **
         2672  +  ** Set or query the content of a MEMDB database.
         2673  +  **
         2674  +  */
         2675  +  case DB_MEMDB: {
         2676  +#ifndef SQLITE_ENABLE_MEMDB
         2677  +    Tcl_AppendResult(interp, "MEMDB not available in this build",
         2678  +                     (char*)0);
         2679  +    rc = TCL_ERROR;
         2680  +#else
         2681  +    const char *zSchema = Tcl_GetString(objv[2]);
         2682  +    sqlite3_int64 sz = 0;
         2683  +    unsigned char *pData;
         2684  +    if( objc==3 ){
         2685  +      pData = sqlite3_memdb_ptr(pDb->db, zSchema, &sz);
         2686  +      if( pData==0 ){
         2687  +        Tcl_AppendResult(interp, "not a MEMDB database", (char*)0);
         2688  +        rc = TCL_ERROR;
         2689  +      }else{
         2690  +        Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));
         2691  +      }
         2692  +    }else if( objc==4 ){
         2693  +      int len = 0, xrc;
         2694  +      unsigned char *pBA = Tcl_GetByteArrayFromObj(objv[3], &len);
         2695  +      pData = sqlite3_malloc64( len );
         2696  +      if( pData==0 ){
         2697  +        Tcl_AppendResult(interp, "out of memory", (char*)0);
         2698  +        rc = TCL_ERROR;
         2699  +      }else{
         2700  +        memcpy(pData, pBA, len);
         2701  +        xrc = sqlite3_memdb_config(pDb->db, zSchema, pData, len, len,
         2702  +                  SQLITE_MEMDB_FREEONCLOSE|SQLITE_MEMDB_RESIZEABLE);
         2703  +        if( xrc ){
         2704  +          sqlite3_free(pData);
         2705  +          Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
         2706  +          rc = TCL_ERROR;
         2707  +        }
         2708  +      }
         2709  +    }else{
         2710  +      Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
         2711  +      rc = TCL_ERROR;
         2712  +    }
         2713  +#endif
         2714  +    break;
         2715  +  }
  2669   2716   
  2670   2717     /*
  2671   2718     **     $db nullvalue ?STRING?
  2672   2719     **
  2673   2720     ** Change text used when a NULL comes back from the database. If ?STRING?
  2674   2721     ** is not present, then the current string used for NULL is returned.
  2675   2722     ** If STRING is present, then STRING is returned.

Changes to src/test_config.c.

   143    143   #endif
   144    144   
   145    145   #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
   146    146     Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "1", TCL_GLOBAL_ONLY);
   147    147   #else
   148    148     Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY);
   149    149   #endif
          150  +
          151  +#ifdef SQLITE_ENABLE_MEMDB
          152  +  Tcl_SetVar2(interp, "sqlite_options", "memdb", "1", TCL_GLOBAL_ONLY);
          153  +#else
          154  +  Tcl_SetVar2(interp, "sqlite_options", "memdb", "0", TCL_GLOBAL_ONLY);
          155  +#endif
   150    156   
   151    157   #ifdef SQLITE_ENABLE_MEMSYS3
   152    158     Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
   153    159   #else
   154    160     Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY);
   155    161   #endif
   156    162   

Added test/memdb1.test.

            1  +# 2018-01-02
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is the "memdb" VFS
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix memdb1
           18  +do_not_use_codec
           19  +
           20  +ifcapable !memdb {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +# Create a MEMDB and populate it with some dummy data.
           26  +# Then extract the database into the $::db1 variable.
           27  +# Verify that the size of $::db1 is the same as the size of
           28  +# the database.
           29  +#
           30  +db close
           31  +sqlite3 db dummy -vfs memdb
           32  +unset -nocomplain db1
           33  +unset -nocomplain sz1
           34  +unset -nocomplain pgsz
           35  +do_test 100 {
           36  +  db eval {
           37  +    CREATE TABLE t1(a,b);
           38  +    INSERT INTO t1 VALUES(1,2);
           39  +  }
           40  +  set ::pgsz [db one {PRAGMA page_size}]
           41  +  set ::sz1 [expr {$::pgsz*[db one {PRAGMA page_count}]}]
           42  +  set ::db1 [db memdb main]
           43  +  expr {[string length $::db1]==$::sz1}
           44  +} 1
           45  +
           46  +# Create a new MEMDB and initialize it to the content of $::db1
           47  +# Verify that the content is the same.
           48  +#
           49  +db close
           50  +sqlite3 db dummy2 -vfs memdb
           51  +db memdb main $db1
           52  +do_execsql_test 110 {
           53  +  SELECT * FROM t1;
           54  +} {1 2}
           55  +
           56  +
           57  +finish_test

Changes to tool/mksqlite3c.tcl.

   316    316      utf.c
   317    317      util.c
   318    318      hash.c
   319    319      opcodes.c
   320    320   
   321    321      os_unix.c
   322    322      os_win.c
          323  +   memdb.c
   323    324   
   324    325      bitvec.c
   325    326      pcache.c
   326    327      pcache1.c
   327    328      rowset.c
   328    329      pager.c
   329    330      wal.c