From ac442f41c134b1242baf488cd53ff57e64deb448 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 01:28:46 +0000 Subject: [PATCH 01/14] 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. FossilOrigin-Name: fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a --- Makefile.in | 6 +- Makefile.msc | 6 +- main.mk | 3 +- manifest | 35 ++-- manifest.uuid | 2 +- src/main.c | 7 +- src/memdb.c | 497 ++++++++++++++++++++++++++++++++++++++++++++ src/pager.c | 6 +- src/sqlite.h.in | 40 ++++ src/sqliteInt.h | 4 + src/tclsqlite.c | 77 +++++-- src/test_config.c | 6 + test/memdb1.test | 57 +++++ tool/mksqlite3c.tcl | 1 + 14 files changed, 710 insertions(+), 37 deletions(-) create mode 100644 src/memdb.c create mode 100644 test/memdb1.test diff --git a/Makefile.in b/Makefile.in index e3dfb01baa..0b326ebd59 100644 --- a/Makefile.in +++ b/Makefile.in @@ -180,7 +180,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo json1.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ - memjournal.lo \ + memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ @@ -240,6 +240,7 @@ SRC = \ $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ + $(TOP)/src/memdb.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/msvc.h \ $(TOP)/src/mutex.c \ @@ -824,6 +825,9 @@ mem3.lo: $(TOP)/src/mem3.c $(HDR) mem5.lo: $(TOP)/src/mem5.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c +memdb.lo: $(TOP)/src/memdb.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memdb.c + memjournal.lo: $(TOP)/src/memjournal.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memjournal.c diff --git a/Makefile.msc b/Makefile.msc index 2f038ab1c1..35eb97261d 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1101,7 +1101,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ - memjournal.lo \ + memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ @@ -1174,6 +1174,7 @@ SRC00 = \ $(TOP)\src\mem2.c \ $(TOP)\src\mem3.c \ $(TOP)\src\mem5.c \ + $(TOP)\src\memdb.c \ $(TOP)\src\memjournal.c \ $(TOP)\src\mutex.c \ $(TOP)\src\mutex_noop.c \ @@ -1807,6 +1808,9 @@ mem3.lo: $(TOP)\src\mem3.c $(HDR) mem5.lo: $(TOP)\src\mem5.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c +memdb.lo: $(TOP)\src\memjournal.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c + memjournal.lo: $(TOP)\src\memjournal.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c diff --git a/main.mk b/main.mk index 85588cd01a..4e13c3e608 100644 --- a/main.mk +++ b/main.mk @@ -65,7 +65,7 @@ LIBOBJ+= vdbe.o parse.o \ fts3_write.o fts5.o func.o global.o hash.o \ icu.o insert.o json1.o legacy.o loadext.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ - memjournal.o \ + memdb.o memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ @@ -118,6 +118,7 @@ SRC = \ $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ + $(TOP)/src/memdb.c \ $(TOP)/src/memjournal.c \ $(TOP)/src/msvc.h \ $(TOP)/src/mutex.c \ diff --git a/manifest b/manifest index 774549626b..f282ff78d7 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Fix\scode\sindentation.\s\sNo\slogic\schanges. -D 2018-01-02T21:29:42.540 -F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 +C Add\ssupport\sfor\sthe\s"memdb"\sVFS\sand\sthe\ssqlite3_memdb_ptr()\sand\nsqlite3_memdb_config()\sinterfaces,\sto\senable\san\sSQLite\sdatabase\sto\sbe\nmanipulated\sas\san\sin-memory\sobject. +D 2018-01-03T01:28:46.871 +F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 +F Makefile.msc bddc04c05f1ab348be051da17827b123fa004005c9ee47489eaf3a2759dcdc45 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -401,7 +401,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 59744c818d349d170ff56cdbdfb5af0e0a2029db18ce2824fcd1b0a3fa317d84 +F main.mk da996649117a4563f04b046d73ce82237ff544138b252245111703f6b916fcd4 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -443,13 +443,14 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 14686083cedc198540b15a79586cdd4be2acf6d5fa97627e355f817ab07e9fee F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b -F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876 +F src/main.c 37139a23caa1a9864b42b0e4bd6416b0d9387e8a7423ebd0ca70f32d03018f46 F src/malloc.c 6f684fd039f53bf9195193eb0cde731a2954970fabc6ef054ba379b6052dc296 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 +F src/memdb.c 46109bc6c890c21a802b6aad6e667c81aee53e5623e2068c6fa9ded1b9634558 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -465,7 +466,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 7fc2735390a7809d5d893ed735d994ff12521224b89738226fff6f1a0aa1c932 F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 9b9cb4e06c03d43d62480a7a685a012d645fcf3a39e7767ccb505fb41ee083ec +F src/pager.c ede1e65f465f6c507c876b87c3f796a7809b52bd9f82da14bac2680f5df8ebe6 F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a F src/parse.y 44cbbc3e132ea128258eff7be7f6d5c5dfa25522f89ec8b5501276966511bd50 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 @@ -480,14 +481,14 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 -F src/sqlite.h.in c597ba5d11666bb2d0179a173cd25e44f0b0333f9e18ce60b07eac8bdc3de67f +F src/sqlite.h.in 8b6cd7fd8b286d567bcc1ee3a750686cbb1c0962dc453b2cfa034684fe5808db F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 +F src/sqliteInt.h 2567341e37050ad542d57f3027b8717cb9b14ff363fdfeecf85421e0d973787f F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 1833388c01e3b77f4c712185ee7250b9423ee0981ce6ae7e401e47db0319a696 +F src/tclsqlite.c 45bcce558f40f245e25d1dd7c208f6845137fbee042cced2a4116f05349ffd9d F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -503,7 +504,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c cc8a1d44648d9392a14f4ecfc841d027daaf61f952b9f70792edf11373aaa3dd +F src/test_config.c 6b749332d98924c52d5b08d1fd847bbe8ff049fc4446af738e64e2532a804348 F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -1055,6 +1056,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 +F test/memdb1.test 3d8ebffdc64ea1a7b4ccacd5502e61191233d979451747f4af88c9f2ee9b34c5 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1628,7 +1630,7 @@ F tool/mkshellc.tcl 574307265b49d813301fba91ccd74e6a26d33f65f74b6891c320a0ffbee0 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb -F tool/mksqlite3c.tcl 1fb69d39166f52d802a70ec37d99bca51d011c8ab30be27bc495be493196ae41 +F tool/mksqlite3c.tcl a03cee30de81a2e67b93e5c659f24113a003677c557daeb008205c8e6d4345d6 F tool/mksqlite3h.tcl f92f994d9709aeb9e2b6e6f9fc8b069d2f55202c8e23f453edc44390a25982dc F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5 @@ -1688,7 +1690,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f -R 9613ba300b7bd9cce413f2672960fb05 +P e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 +R dd0ff0dcdd2908eb59154bae6d4e7abd +T *branch * memdb +T *sym-memdb * +T -sym-trunk * U drh -Z 9fca118926b581510cc96e0ce3702687 +Z 4f847deac1204c1b3d7c3decd276393a diff --git a/manifest.uuid b/manifest.uuid index 4bf24d86c2..1ad14f7d1d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 \ No newline at end of file +fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a \ No newline at end of file diff --git a/src/main.c b/src/main.c index 3c8035c120..bcede6483f 100644 --- a/src/main.c +++ b/src/main.c @@ -239,6 +239,11 @@ int sqlite3_initialize(void){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } +#ifdef SQLITE_ENABLE_MEMDB + if( rc==SQLITE_OK ){ + rc = sqlite3MemdbInit(); + } +#endif if( rc==SQLITE_OK ){ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); @@ -271,7 +276,7 @@ int sqlite3_initialize(void){ #ifndef NDEBUG #ifndef SQLITE_OMIT_FLOATING_POINT /* This section of code's only "output" is via assert() statements. */ - if ( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ u64 x = (((u64)1)<<63)-1; double y; assert(sizeof(x)==8); diff --git a/src/memdb.c b/src/memdb.c new file mode 100644 index 0000000000..7392513126 --- /dev/null +++ b/src/memdb.c @@ -0,0 +1,497 @@ +/* +** 2016-09-07 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This is an in-memory VFS implementation. The application supplies +** a chunk of memory to hold the database file. +** +** USAGE: +** +** sqlite3_open_v2("whatever", &db, SQLITE_OPEN_READWRITE, "memdb"); +** void *sqlite3_memdb_ptr(db, "main", &sz); +** int sqlite3_memdb_config(db, "main", pMem, szData, szMem, mFlags); +** +** Flags: +** +** SQLITE_MEMDB_FREEONCLOSE Free pMem when closing the connection +** SQLITE_MEMDB_RESIZEABLE Use sqlite3_realloc64() to resize pMem +*/ +#ifdef SQLITE_ENABLE_MEMDB +#include "sqliteInt.h" + +/* +** Forward declaration of objects used by this utility +*/ +typedef struct sqlite3_vfs MemVfs; +typedef struct MemFile MemFile; + +/* Access to a lower-level VFS that (might) implement dynamic loading, +** access to randomness, etc. +*/ +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) + +/* An open file */ +struct MemFile { + sqlite3_file base; /* IO methods */ + sqlite3_int64 sz; /* Size of the file */ + sqlite3_int64 szMax; /* Space allocated to aData */ + unsigned char *aData; /* content of the file */ + int nMmap; /* Number of memory mapped pages */ + unsigned mFlags; /* Flags */ + int eLock; /* Most recent lock against this file */ +}; + +/* +** Methods for MemFile +*/ +static int memdbClose(sqlite3_file*); +static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); +static int memdbSync(sqlite3_file*, int flags); +static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int memdbLock(sqlite3_file*, int); +static int memdbCheckReservedLock(sqlite3_file*, int *pResOut); +static int memdbFileControl(sqlite3_file*, int op, void *pArg); +static int memdbSectorSize(sqlite3_file*); +static int memdbDeviceCharacteristics(sqlite3_file*); +static int memdbShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**); +static int memdbShmLock(sqlite3_file*, int offset, int n, int flags); +static void memdbShmBarrier(sqlite3_file*); +static int memdbShmUnmap(sqlite3_file*, int deleteFlag); +static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); +static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); + +/* +** Methods for MemVfs +*/ +static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); +static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); +static void memdbDlClose(sqlite3_vfs*, void*); +static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int memdbSleep(sqlite3_vfs*, int microseconds); +static int memdbCurrentTime(sqlite3_vfs*, double*); +static int memdbGetLastError(sqlite3_vfs*, int, char *); +static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); + +static sqlite3_vfs memdb_vfs = { + 2, /* iVersion */ + 0, /* szOsFile (set when registered) */ + 1024, /* mxPathname */ + 0, /* pNext */ + "memdb", /* zName */ + 0, /* pAppData (set when registered) */ + memdbOpen, /* xOpen */ + memdbDelete, /* xDelete */ + memdbAccess, /* xAccess */ + memdbFullPathname, /* xFullPathname */ + memdbDlOpen, /* xDlOpen */ + memdbDlError, /* xDlError */ + memdbDlSym, /* xDlSym */ + memdbDlClose, /* xDlClose */ + memdbRandomness, /* xRandomness */ + memdbSleep, /* xSleep */ + memdbCurrentTime, /* xCurrentTime */ + memdbGetLastError, /* xGetLastError */ + memdbCurrentTimeInt64 /* xCurrentTimeInt64 */ +}; + +static const sqlite3_io_methods memdb_io_methods = { + 3, /* iVersion */ + memdbClose, /* xClose */ + memdbRead, /* xRead */ + memdbWrite, /* xWrite */ + memdbTruncate, /* xTruncate */ + memdbSync, /* xSync */ + memdbFileSize, /* xFileSize */ + memdbLock, /* xLock */ + memdbLock, /* xUnlock - same as xLock in this case */ + memdbCheckReservedLock, /* xCheckReservedLock */ + memdbFileControl, /* xFileControl */ + memdbSectorSize, /* xSectorSize */ + memdbDeviceCharacteristics, /* xDeviceCharacteristics */ + memdbShmMap, /* xShmMap */ + memdbShmLock, /* xShmLock */ + memdbShmBarrier, /* xShmBarrier */ + memdbShmUnmap, /* xShmUnmap */ + memdbFetch, /* xFetch */ + memdbUnfetch /* xUnfetch */ +}; + + + +/* +** Close an memdb-file. +** +** The pData pointer is owned by the application, so there is nothing +** to free. +*/ +static int memdbClose(sqlite3_file *pFile){ + MemFile *p = (MemFile *)pFile; + if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); + return SQLITE_OK; +} + +/* +** Read data from an memdb-file. +*/ +static int memdbRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + memset(zBuf, 0, iAmt); + return SQLITE_IOERR_SHORT_READ; + } + memcpy(zBuf, p->aData+iOfst, iAmt); + return SQLITE_OK; +} + +/* +** Try to enlarge the memory allocation to hold at least sz bytes +*/ +static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ + unsigned char *pNew; + if( (p->mFlags & SQLITE_MEMDB_RESIZEABLE)==0 ) return SQLITE_FULL; + if( p->nMmap>0 ) return SQLITE_FULL; + pNew = sqlite3_realloc64(p->aData, newSz); + if( pNew==0 ) return SQLITE_FULL; + p->aData = pNew; + p->szMax = newSz; + return SQLITE_OK; +} + +/* +** Write data to an memdb-file. +*/ +static int memdbWrite( + sqlite3_file *pFile, + const void *z, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + if( iOfst+iAmt>p->szMax && memdbEnlarge(p, (iOfst+iAmt)*2) ){ + return SQLITE_FULL; + } + if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); + p->sz = iOfst+iAmt; + } + memcpy(p->aData+iOfst, z, iAmt); + return SQLITE_OK; +} + +/* +** Truncate an memdb-file. +*/ +static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ + MemFile *p = (MemFile *)pFile; + if( size>p->sz ){ + if( size>p->szMax && memdbEnlarge(p, size) ) return SQLITE_FULL; + memset(p->aData+p->sz, 0, size-p->sz); + } + p->sz = size; + return SQLITE_OK; +} + +/* +** Sync an memdb-file. +*/ +static int memdbSync(sqlite3_file *pFile, int flags){ + return SQLITE_OK; +} + +/* +** Return the current file-size of an memdb-file. +*/ +static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + MemFile *p = (MemFile *)pFile; + *pSize = p->sz; + return SQLITE_OK; +} + +/* +** Lock an memdb-file. +*/ +static int memdbLock(sqlite3_file *pFile, int eLock){ + MemFile *p = (MemFile *)pFile; + p->eLock = eLock; + return SQLITE_OK; +} + +/* +** Check if another file-handle holds a RESERVED lock on an memdb-file. +*/ +static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** File control method. For custom operations on an memdb-file. +*/ +static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ + MemFile *p = (MemFile *)pFile; + int rc = SQLITE_NOTFOUND; + if( op==SQLITE_FCNTL_VFSNAME ){ + *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); + rc = SQLITE_OK; + } + return rc; +} + +/* +** Return the sector-size in bytes for an memdb-file. +*/ +static int memdbSectorSize(sqlite3_file *pFile){ + return 1024; +} + +/* +** Return the device characteristic flags supported by an memdb-file. +*/ +static int memdbDeviceCharacteristics(sqlite3_file *pFile){ + return SQLITE_IOCAP_ATOMIC | + SQLITE_IOCAP_POWERSAFE_OVERWRITE | + SQLITE_IOCAP_SAFE_APPEND | + SQLITE_IOCAP_SEQUENTIAL; +} + +/* Create a shared memory file mapping */ +static int memdbShmMap( + sqlite3_file *pFile, + int iPg, + int pgsz, + int bExtend, + void volatile **pp +){ + return SQLITE_IOERR_SHMMAP; +} + +/* Perform locking on a shared-memory segment */ +static int memdbShmLock(sqlite3_file *pFile, int offset, int n, int flags){ + return SQLITE_IOERR_SHMLOCK; +} + +/* Memory barrier operation on shared memory */ +static void memdbShmBarrier(sqlite3_file *pFile){ + return; +} + +/* Unmap a shared memory segment */ +static int memdbShmUnmap(sqlite3_file *pFile, int deleteFlag){ + return SQLITE_OK; +} + +/* Fetch a page of a memory-mapped file */ +static int memdbFetch( + sqlite3_file *pFile, + sqlite3_int64 iOfst, + int iAmt, + void **pp +){ + MemFile *p = (MemFile *)pFile; + p->nMmap++; + *pp = (void*)(p->aData + iOfst); + return SQLITE_OK; +} + +/* Release a memory-mapped page */ +static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ + MemFile *p = (MemFile *)pFile; + p->nMmap--; + return SQLITE_OK; +} + +/* +** Open an mem file handle. +*/ +static int memdbOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + MemFile *p = (MemFile*)pFile; + memset(p, 0, sizeof(*p)); + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN; + p->mFlags = SQLITE_MEMDB_RESIZEABLE | SQLITE_MEMDB_FREEONCLOSE; + *pOutFlags = flags | SQLITE_OPEN_MEMORY; + p->base.pMethods = &memdb_io_methods; + return SQLITE_OK; +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return SQLITE_IOERR_DELETE; +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int memdbAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int memdbFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + return SQLITE_OK; +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ + return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ + ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ + return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); +} + +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); +} + +static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ + return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); +} +static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ + return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); +} + +/* +** Translate a database connection pointer and schema name into a +** MemFile pointer. +*/ +static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ + MemFile *p = 0; + int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); + if( rc ) return 0; + if( p->base.pMethods!=&memdb_io_methods ) return 0; + return p; +} + +/* +** Return a pointer to the memory used to hold the database. +** Return NULL if the arguments do not describe a memdb database. +*/ +void *sqlite3_memdb_ptr(sqlite3 *db, const char *zSchema, sqlite3_int64 *pSz){ + MemFile *p = memdbFromDbSchema(db, zSchema); + if( p==0 ){ + *pSz = 0; + return 0; + } + *pSz = p->sz; + return p->aData; +} + +/* +** Reconfigure a memdb database. +*/ +int sqlite3_memdb_config( + sqlite3 *db, + const char *zSchema, + void *aData, + sqlite3_int64 sz, + sqlite3_int64 szMax, + unsigned int mFlags +){ + MemFile *p = memdbFromDbSchema(db, zSchema); + if( p==0 ) return SQLITE_ERROR; + if( p->eLock!=SQLITE_LOCK_NONE || p->nMmap>0 ) return SQLITE_BUSY; + if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); + p->aData = aData; + p->sz = sz; + p->szMax = szMax; + p->mFlags = mFlags; + return SQLITE_OK; +} + +/* +** This routine is called when the extension is loaded. +** Register the new VFS. +*/ +int sqlite3MemdbInit(void){ + memdb_vfs.pAppData = sqlite3_vfs_find(0); + memdb_vfs.szOsFile = sizeof(MemFile); + return sqlite3_vfs_register(&memdb_vfs, 0); +} +#endif /* SQLITE_ENABLE_MEMDB */ diff --git a/src/pager.c b/src/pager.c index 295cbe04c5..4f50963b22 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4694,6 +4694,7 @@ int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ + int memJM = 0; /* Memory journal mode */ int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ @@ -4821,7 +4822,8 @@ int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); - readOnly = (fout&SQLITE_OPEN_READONLY); + memJM = (fout&SQLITE_OPEN_MEMORY)!=0; + readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, ** choose a default page size in case we have to create the @@ -4952,7 +4954,7 @@ act_like_temp_file: setSectorSize(pPager); if( !useJournal ){ pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb ){ + }else if( memDb || memJM ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index a6d328360a..1434485532 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8758,6 +8758,46 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Retrieve the current MEMDB buffer +** EXPERIMENTAL +** +** This interface is only available when SQLite is compiled +** with SQLITE_ENABLE_MEMDB. +** +** The sqlite3_memdb_ptr(D,S,P) interface returns a pointer to the +** memory buffer that is the database file used for [database connection] D +** and schema S. If schema S of database connection D is not a MEMDB +** database, then this routine returns NULL. If P is not NULL, then it must +** be a pointer to a 64-bit signed integer into which the size of the +** database file is written. +*/ +SQLITE_EXPERIMENTAL void *sqlite3_memdb_ptr(sqlite3*,const char*,sqlite3_int64*); + +/* +** CAPI3REF: Set the current MEMDB buffer +** EXPERIMENTAL +** +** This interface is only available when SQLite is compiled +** with SQLITE_ENABLE_MEMDB. +** +** The sqlite3_memdb_config(D,S,P,N,M,F) interface initializes a MEMDB database. +** The database identified by D and S must not be in active use when this +** interface is called, or [SQLITE_BUSY] is returned. +*/ +SQLITE_EXPERIMENTAL int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_int64,sqlite3_int64,unsigned); + +/* +** CAPI3REF: Flags for configuring MEMDB databases +** EXPERIMENTAL +** +** The following are allowed values for the 6th argument (the "flags" +** argument) of the [sqlite3_memdb_config()] interface. +*/ +#define SQLITE_MEMDB_FREEONCLOSE 0x001 /* Free the memory buffer on close */ +#define SQLITE_MEMDB_RESIZEABLE 0x002 /* Resize using sqlite3_realloc64() */ + + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8e79133200..002fb4e916 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4019,6 +4019,10 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); const char *sqlite3ErrName(int); #endif +#ifdef SQLITE_ENABLE_MEMDB +int sqlite3MemdbInit(void); +#endif + const char *sqlite3ErrStr(int); int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index eed86eee34..0e86d727b3 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1852,14 +1852,13 @@ static int SQLITE_TCLAPI DbObjCmd( "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "incrblob", "interrupt", - "last_insert_rowid", "nullvalue", "onecolumn", - "preupdate", "profile", "progress", - "rekey", "restore", "rollback_hook", - "status", "timeout", "total_changes", - "trace", "trace_v2", "transaction", - "unlock_notify", "update_hook", "version", - "wal_hook", - 0 + "last_insert_rowid", "memdb", "nullvalue", + "onecolumn", "preupdate", "profile", + "progress", "rekey", "restore", + "rollback_hook", "status", "timeout", + "total_changes", "trace", "trace_v", + "transaction", "unlock_notify", "update_hook", + "version", "wal_hook", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BUSY, @@ -1868,13 +1867,13 @@ static int SQLITE_TCLAPI DbObjCmd( DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, - DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, - DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, - DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, - DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, - DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, - DB_WAL_HOOK, + DB_LAST_INSERT_ROWID, DB_MEMDB, DB_NULLVALUE, + DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, + DB_PROGRESS, DB_REKEY, DB_RESTORE, + DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, + DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2, + DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, + DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2667,6 +2666,54 @@ static int SQLITE_TCLAPI DbObjCmd( break; } + /* + ** $db memdb DATABASE ?BLOB? + ** + ** Set or query the content of a MEMDB database. + ** + */ + case DB_MEMDB: { +#ifndef SQLITE_ENABLE_MEMDB + Tcl_AppendResult(interp, "MEMDB not available in this build", + (char*)0); + rc = TCL_ERROR; +#else + const char *zSchema = Tcl_GetString(objv[2]); + sqlite3_int64 sz = 0; + unsigned char *pData; + if( objc==3 ){ + pData = sqlite3_memdb_ptr(pDb->db, zSchema, &sz); + if( pData==0 ){ + Tcl_AppendResult(interp, "not a MEMDB database", (char*)0); + rc = TCL_ERROR; + }else{ + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz)); + } + }else if( objc==4 ){ + int len = 0, xrc; + unsigned char *pBA = Tcl_GetByteArrayFromObj(objv[3], &len); + pData = sqlite3_malloc64( len ); + if( pData==0 ){ + Tcl_AppendResult(interp, "out of memory", (char*)0); + rc = TCL_ERROR; + }else{ + memcpy(pData, pBA, len); + xrc = sqlite3_memdb_config(pDb->db, zSchema, pData, len, len, + SQLITE_MEMDB_FREEONCLOSE|SQLITE_MEMDB_RESIZEABLE); + if( xrc ){ + sqlite3_free(pData); + Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); + rc = TCL_ERROR; + } + } + }else{ + Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); + rc = TCL_ERROR; + } +#endif + break; + } + /* ** $db nullvalue ?STRING? ** diff --git a/src/test_config.c b/src/test_config.c index ad63016baf..aeb3393f0b 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -148,6 +148,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_MEMDB + Tcl_SetVar2(interp, "sqlite_options", "memdb", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memdb", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_MEMSYS3 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); #else diff --git a/test/memdb1.test b/test/memdb1.test new file mode 100644 index 0000000000..2be9cf62c5 --- /dev/null +++ b/test/memdb1.test @@ -0,0 +1,57 @@ +# 2018-01-02 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is the "memdb" VFS +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix memdb1 +do_not_use_codec + +ifcapable !memdb { + finish_test + return +} + +# Create a MEMDB and populate it with some dummy data. +# Then extract the database into the $::db1 variable. +# Verify that the size of $::db1 is the same as the size of +# the database. +# +db close +sqlite3 db dummy -vfs memdb +unset -nocomplain db1 +unset -nocomplain sz1 +unset -nocomplain pgsz +do_test 100 { + db eval { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,2); + } + set ::pgsz [db one {PRAGMA page_size}] + set ::sz1 [expr {$::pgsz*[db one {PRAGMA page_count}]}] + set ::db1 [db memdb main] + expr {[string length $::db1]==$::sz1} +} 1 + +# Create a new MEMDB and initialize it to the content of $::db1 +# Verify that the content is the same. +# +db close +sqlite3 db dummy2 -vfs memdb +db memdb main $db1 +do_execsql_test 110 { + SELECT * FROM t1; +} {1 2} + + +finish_test diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 8ea3e81c91..f2d93aadd0 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -320,6 +320,7 @@ foreach file { os_unix.c os_win.c + memdb.c bitvec.c pcache.c From 7de2c3e5eee332de01158b6f99bb71af86e28de5 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 3 Jan 2018 12:39:35 +0000 Subject: [PATCH 02/14] Fix typo in the Makefile for MSVC. FossilOrigin-Name: e5c6ade8ee596eaffd98d1d7ce9c7c968cd2d45f206603b894026e7ad7ac15b6 --- Makefile.msc | 2 +- manifest | 17 +++++++---------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 35eb97261d..b063b1226f 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1808,7 +1808,7 @@ mem3.lo: $(TOP)\src\mem3.c $(HDR) mem5.lo: $(TOP)\src\mem5.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c -memdb.lo: $(TOP)\src\memjournal.c $(HDR) +memdb.lo: $(TOP)\src\memdb.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c memjournal.lo: $(TOP)\src\memjournal.c $(HDR) diff --git a/manifest b/manifest index f282ff78d7..375e1b52c1 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\ssupport\sfor\sthe\s"memdb"\sVFS\sand\sthe\ssqlite3_memdb_ptr()\sand\nsqlite3_memdb_config()\sinterfaces,\sto\senable\san\sSQLite\sdatabase\sto\sbe\nmanipulated\sas\san\sin-memory\sobject. -D 2018-01-03T01:28:46.871 +C Fix\stypo\sin\sthe\sMakefile\sfor\sMSVC. +D 2018-01-03T12:39:35.460 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc bddc04c05f1ab348be051da17827b123fa004005c9ee47489eaf3a2759dcdc45 +F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1690,10 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 -R dd0ff0dcdd2908eb59154bae6d4e7abd -T *branch * memdb -T *sym-memdb * -T -sym-trunk * -U drh -Z 4f847deac1204c1b3d7c3decd276393a +P fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a +R 025ad5693b1eb347e4b6ac2d4f7892d8 +U mistachkin +Z 11bcd34cb283c66a6b2991d9a37cef7f diff --git a/manifest.uuid b/manifest.uuid index 1ad14f7d1d..624e8aa98f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a \ No newline at end of file +e5c6ade8ee596eaffd98d1d7ce9c7c968cd2d45f206603b894026e7ad7ac15b6 \ No newline at end of file From 4dcac40e3d4cf02513c84c95ccd4198ef35f2320 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 13:20:02 +0000 Subject: [PATCH 03/14] Simplify the "sqlite3" command in the TCL interface. The filename is now optional. There is a new --memdb option with an argument that is the blob to which the database content should be initialized. FossilOrigin-Name: 47398ae77236a92f6b9345aa397361b6df127a9a2895c0771d506b0be10822b9 --- manifest | 20 +++++----- manifest.uuid | 2 +- src/memdb.c | 23 ++++++++---- src/tclsqlite.c | 89 ++++++++++++++++++++++++++++++++------------- test/memdb1.test | 3 +- test/tclsqlite.test | 6 +-- 6 files changed, 94 insertions(+), 49 deletions(-) diff --git a/manifest b/manifest index 375e1b52c1..9d5dca5c2b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sin\sthe\sMakefile\sfor\sMSVC. -D 2018-01-03T12:39:35.460 +C Simplify\sthe\s"sqlite3"\scommand\sin\sthe\sTCL\sinterface.\s\sThe\sfilename\sis\snow\noptional.\s\sThere\sis\sa\snew\s--memdb\soption\swith\san\sargument\sthat\sis\sthe\sblob\nto\swhich\sthe\sdatabase\scontent\sshould\sbe\sinitialized. +D 2018-01-03T13:20:02.897 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -450,7 +450,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c 46109bc6c890c21a802b6aad6e667c81aee53e5623e2068c6fa9ded1b9634558 +F src/memdb.c 13c69aee0185614a25303e2be3802b73416e655e95e1f1c607a9f963b35a1def F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -488,7 +488,7 @@ F src/sqliteInt.h 2567341e37050ad542d57f3027b8717cb9b14ff363fdfeecf85421e0d97378 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 45bcce558f40f245e25d1dd7c208f6845137fbee042cced2a4116f05349ffd9d +F src/tclsqlite.c 907133153d3194ddfd728e84f55fa106de696dc644c9508a054c72b9f833972e F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -1056,7 +1056,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test 3d8ebffdc64ea1a7b4ccacd5502e61191233d979451747f4af88c9f2ee9b34c5 +F test/memdb1.test 1d94a4bf153201f16a0a755a5a0a5d7f33b001c972e3086acb1f76ad3fb7e0e5 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1282,7 +1282,7 @@ F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test c3d7ac9449634b9f17fd048a3c0212e88a7448be810a9c5bd051acc1ffa00d2f +F test/tclsqlite.test 45462ee8dd0ca4fd95a476c9253d332ce2cf90985cb0ad5c7eae6e8c7fe24ae8 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/tempdb2.test 27e41ed540b2f9b056c2e77e9bddc1b875358507 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fb2ac2d2fa6374084f3325b41b257c7a3ace43aade4b666ec4be93b6b70dc39a -R 025ad5693b1eb347e4b6ac2d4f7892d8 -U mistachkin -Z 11bcd34cb283c66a6b2991d9a37cef7f +P e5c6ade8ee596eaffd98d1d7ce9c7c968cd2d45f206603b894026e7ad7ac15b6 +R 66054801a2fc399d3dc7a916643e1819 +U drh +Z 2a01cfd70faa22757159c69df08c3c76 diff --git a/manifest.uuid b/manifest.uuid index 624e8aa98f..2905c1c5a6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e5c6ade8ee596eaffd98d1d7ce9c7c968cd2d45f206603b894026e7ad7ac15b6 \ No newline at end of file +47398ae77236a92f6b9345aa397361b6df127a9a2895c0771d506b0be10822b9 \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index 7392513126..215bfbb24a 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -475,13 +475,22 @@ int sqlite3_memdb_config( unsigned int mFlags ){ MemFile *p = memdbFromDbSchema(db, zSchema); - if( p==0 ) return SQLITE_ERROR; - if( p->eLock!=SQLITE_LOCK_NONE || p->nMmap>0 ) return SQLITE_BUSY; - if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); - p->aData = aData; - p->sz = sz; - p->szMax = szMax; - p->mFlags = mFlags; + int rc; + if( p==0 ){ + rc = SQLITE_ERROR; + }else if( p->eLock!=SQLITE_LOCK_NONE || p->nMmap>0 ){ + rc = SQLITE_BUSY; + }else{ + if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); + p->aData = aData; + p->sz = sz; + p->szMax = szMax; + p->mFlags = mFlags; + rc = SQLITE_OK; + } + if( rc!=SQLITE_OK && (mFlags & SQLITE_MEMDB_FREEONCLOSE)!=0 ){ + sqlite3_free(aData); + } return SQLITE_OK; } diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 0e86d727b3..d02d94baf5 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1856,7 +1856,7 @@ static int SQLITE_TCLAPI DbObjCmd( "onecolumn", "preupdate", "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", - "total_changes", "trace", "trace_v", + "total_changes", "trace", "trace_v2", "transaction", "unlock_notify", "update_hook", "version", "wal_hook", 0 }; @@ -2701,7 +2701,6 @@ static int SQLITE_TCLAPI DbObjCmd( xrc = sqlite3_memdb_config(pDb->db, zSchema, pData, len, len, SQLITE_MEMDB_FREEONCLOSE|SQLITE_MEMDB_RESIZEABLE); if( xrc ){ - sqlite3_free(pData); Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); rc = TCL_ERROR; } @@ -3394,6 +3393,24 @@ static int SQLITE_TCLAPI DbObjCmdAdaptor( } #endif /* SQLITE_TCL_NRE */ +/* +** Issue the usage message when the "sqlite3" command arguments are +** incorrect. +*/ +static int sqliteCmdUsage( + Tcl_Interp *interp, + Tcl_Obj *const*objv +){ + Tcl_WrongNumArgs(interp, 1, objv, + "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" + " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) + " ?-key CODECKEY?" +#endif + ); + return TCL_ERROR; +} + /* ** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? ** ?-create BOOLEAN? ?-nomutex BOOLEAN? @@ -3419,7 +3436,7 @@ static int SQLITE_TCLAPI DbMain( const char *zArg; char *zErrMsg; int i; - const char *zFile; + const char *zFile = 0; const char *zVfs = 0; int flags; Tcl_DString translatedFilename; @@ -3428,9 +3445,12 @@ static int SQLITE_TCLAPI DbMain( int nKey = 0; #endif int rc; +#ifdef SQLITE_ENABLE_MEMDB + Tcl_Obj *pDbObj = 0; +#endif /* In normal use, each TCL interpreter runs in a single thread. So - ** by default, we can turn of mutexing on SQLite database connections. + ** by default, we can turn off mutexing on SQLite database connections. ** However, for testing purposes it is useful to have mutexes turned ** on. So, by default, mutexes default off. But if compiled with ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. @@ -3459,18 +3479,26 @@ static int SQLITE_TCLAPI DbMain( #endif return TCL_OK; } + if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv); } - for(i=3; i+1db, flags, zVfs); - Tcl_DStringFree(&translatedFilename); +#ifdef SQLITE_ENABLE_MEMDB + if( pDbObj ){ + rc = sqlite3_open_v2("x", &p->db, flags, "memdb"); + if( rc==SQLITE_OK ){ + int len; + unsigned char *aData = Tcl_GetByteArrayFromObj(pDbObj, &len); + unsigned char *a = sqlite3_malloc64( len ); + memcpy(a, aData, len); + sqlite3_memdb_config(p->db, "main", a, len, sqlite3_msize(a), + SQLITE_MEMDB_FREEONCLOSE | SQLITE_MEMDB_RESIZEABLE); + } + }else +#endif + { + if( zFile==0 ) zFile = ":memory:"; + zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); + rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); + Tcl_DStringFree(&translatedFilename); + } if( p->db ){ if( SQLITE_OK!=sqlite3_errcode(p->db) ){ zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); diff --git a/test/memdb1.test b/test/memdb1.test index 2be9cf62c5..13ef57ace4 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -47,8 +47,7 @@ do_test 100 { # Verify that the content is the same. # db close -sqlite3 db dummy2 -vfs memdb -db memdb main $db1 +sqlite3 db -memdb $db1 do_execsql_test 110 { SELECT * FROM t1; } {1 2} diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 1b95a45a5c..ca53710ec2 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -22,19 +22,19 @@ source $testdir/tester.tcl # Check the error messages generated by tclsqlite # -set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" +set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" if {[sqlite3 -has-codec]} { append r " ?-key CODECKEY?" } do_test tcl-1.1 { - set v [catch {sqlite3 bogus} msg] + set v [catch {sqlite3 -bogus} msg] regsub {really_sqlite3} $msg {sqlite3} msg lappend v $msg } [list 1 "wrong # args: should be \"$r\""] do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, memdb, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg From cb7d541d3ae005e24bb0d36bb138d84a3ca3d415 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 16:49:52 +0000 Subject: [PATCH 04/14] Replace the sqlite3_memdb_ptr() interface with the more general sqlite3_serialize() interface. FossilOrigin-Name: 8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077 --- manifest | 20 ++++----- manifest.uuid | 2 +- src/memdb.c | 81 ++++++++++++++++++++++++++++------ src/sqlite.h.in | 111 +++++++++++++++++++++++++++++++++++++++-------- src/tclsqlite.c | 108 ++++++++++++++++++++++++++++++--------------- test/memdb1.test | 7 +-- tool/mkopts.tcl | 4 +- 7 files changed, 250 insertions(+), 83 deletions(-) diff --git a/manifest b/manifest index 9d5dca5c2b..892a7572e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\s"sqlite3"\scommand\sin\sthe\sTCL\sinterface.\s\sThe\sfilename\sis\snow\noptional.\s\sThere\sis\sa\snew\s--memdb\soption\swith\san\sargument\sthat\sis\sthe\sblob\nto\swhich\sthe\sdatabase\scontent\sshould\sbe\sinitialized. -D 2018-01-03T13:20:02.897 +C Replace\sthe\ssqlite3_memdb_ptr()\sinterface\swith\sthe\smore\sgeneral\nsqlite3_serialize()\sinterface. +D 2018-01-03T16:49:52.676 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -450,7 +450,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c 13c69aee0185614a25303e2be3802b73416e655e95e1f1c607a9f963b35a1def +F src/memdb.c 39dd9443f902759b858e598f17afc425c094b0d5f057b7ec988d224d812bd2a3 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -481,14 +481,14 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 -F src/sqlite.h.in 8b6cd7fd8b286d567bcc1ee3a750686cbb1c0962dc453b2cfa034684fe5808db +F src/sqlite.h.in 16bbb15a5fc53bfd725305ec9a201a7f57df7770749aa758b33a0636946d1bb4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqliteInt.h 2567341e37050ad542d57f3027b8717cb9b14ff363fdfeecf85421e0d973787f F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 907133153d3194ddfd728e84f55fa106de696dc644c9508a054c72b9f833972e +F src/tclsqlite.c 322ad6b4e613aba84eee8cf6239eae668167f8b9891ca9e4aa53b78cd3aaff35 F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -1056,7 +1056,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test 1d94a4bf153201f16a0a755a5a0a5d7f33b001c972e3086acb1f76ad3fb7e0e5 +F test/memdb1.test 062cdf3b7de2f861878e4275d3a67b80982d9f792f693418c844fade15ec7537 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1624,7 +1624,7 @@ F tool/mkkeywordhash.c 2e852ac0dfdc5af18886dc1ce7e9676d11714ae3df0a282dc7d90b3a0 F tool/mkmsvcmin.tcl 8baf26690b80d861d0ac341b29880eec6ade39e4f11fe690271ded9cb90563a3 F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee -F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e +F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd F tool/mkshellc.tcl 574307265b49d813301fba91ccd74e6a26d33f65f74b6891c320a0ffbee07895 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e5c6ade8ee596eaffd98d1d7ce9c7c968cd2d45f206603b894026e7ad7ac15b6 -R 66054801a2fc399d3dc7a916643e1819 +P 47398ae77236a92f6b9345aa397361b6df127a9a2895c0771d506b0be10822b9 +R bfc121db68c7d1b10b977a508d74da37 U drh -Z 2a01cfd70faa22757159c69df08c3c76 +Z 6064e9ffbc398d82aebface075258c56 diff --git a/manifest.uuid b/manifest.uuid index 2905c1c5a6..a6d77e2b7f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -47398ae77236a92f6b9345aa397361b6df127a9a2895c0771d506b0be10822b9 \ No newline at end of file +8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077 \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index 215bfbb24a..0a81978cce 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -157,6 +157,7 @@ static int memdbRead( MemFile *p = (MemFile *)pFile; if( iOfst+iAmt>p->sz ){ memset(zBuf, 0, iAmt); + if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); return SQLITE_IOERR_SHORT_READ; } memcpy(zBuf, p->aData+iOfst, iAmt); @@ -449,20 +450,6 @@ static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ return p; } -/* -** Return a pointer to the memory used to hold the database. -** Return NULL if the arguments do not describe a memdb database. -*/ -void *sqlite3_memdb_ptr(sqlite3 *db, const char *zSchema, sqlite3_int64 *pSz){ - MemFile *p = memdbFromDbSchema(db, zSchema); - if( p==0 ){ - *pSz = 0; - return 0; - } - *pSz = p->sz; - return p->aData; -} - /* ** Reconfigure a memdb database. */ @@ -494,6 +481,72 @@ int sqlite3_memdb_config( return SQLITE_OK; } +/* +** Return the serialization of a database +*/ +unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which database within the connection */ + sqlite3_int64 *piSize, /* Write size here, if not NULL */ + unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ +){ + MemFile *p = memdbFromDbSchema(db, zSchema); + int iDb = sqlite3FindDbName(db, zSchema); + Btree *pBt; + sqlite3_int64 sz; + int szPage = 0; + sqlite3_stmt *pStmt = 0; + unsigned char *pOut; + char *zSql; + int rc; + + if( piSize ) *piSize = -1; + if( iDb<0 ) return 0; + if( p ){ + if( piSize ) *piSize = p->sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = p->aData; + }else{ + pOut = sqlite3_malloc64( p->sz ); + if( pOut ) memcpy(pOut, p->aData, p->sz); + } + return pOut; + } + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) return 0; + szPage = sqlite3BtreeGetPageSize(pBt); + zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); + rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; + sqlite3_free(zSql); + if( rc ) return 0; + sqlite3_step(pStmt); + sz = sqlite3_column_int64(pStmt, 0)*szPage; + if( piSize ) *piSize = sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = 0; + }else{ + pOut = sqlite3_malloc64( sz ); + if( pOut ){ + int nPage = sqlite3_column_int(pStmt, 0); + Pager *pPager = sqlite3BtreePager(pBt); + int pgno; + for(pgno=1; pgno<=nPage; pgno++){ + DbPage *pPage = 0; + unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); + rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); + if( rc==SQLITE_OK ){ + memcpy(pTo, sqlite3PagerGetData(pPage), szPage); + }else{ + memset(pTo, 0, szPage); + } + sqlite3PagerUnref(pPage); + } + } + } + sqlite3_finalize(pStmt); + return pOut; +} + /* ** This routine is called when the extension is loaded. ** Register the new VFS. diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 1434485532..6b6a5655b3 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8758,22 +8758,6 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); -/* -** CAPI3REF: Retrieve the current MEMDB buffer -** EXPERIMENTAL -** -** This interface is only available when SQLite is compiled -** with SQLITE_ENABLE_MEMDB. -** -** The sqlite3_memdb_ptr(D,S,P) interface returns a pointer to the -** memory buffer that is the database file used for [database connection] D -** and schema S. If schema S of database connection D is not a MEMDB -** database, then this routine returns NULL. If P is not NULL, then it must -** be a pointer to a 64-bit signed integer into which the size of the -** database file is written. -*/ -SQLITE_EXPERIMENTAL void *sqlite3_memdb_ptr(sqlite3*,const char*,sqlite3_int64*); - /* ** CAPI3REF: Set the current MEMDB buffer ** EXPERIMENTAL @@ -8785,7 +8769,7 @@ SQLITE_EXPERIMENTAL void *sqlite3_memdb_ptr(sqlite3*,const char*,sqlite3_int64*) ** The database identified by D and S must not be in active use when this ** interface is called, or [SQLITE_BUSY] is returned. */ -SQLITE_EXPERIMENTAL int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_int64,sqlite3_int64,unsigned); +int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_int64,sqlite3_int64,unsigned); /* ** CAPI3REF: Flags for configuring MEMDB databases @@ -8797,6 +8781,99 @@ SQLITE_EXPERIMENTAL int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_ #define SQLITE_MEMDB_FREEONCLOSE 0x001 /* Free the memory buffer on close */ #define SQLITE_MEMDB_RESIZEABLE 0x002 /* Resize using sqlite3_realloc64() */ +/* +** CAPI3REF: Serialize a database +** EXPERIMENTAL +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contigous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +*/ +unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** EXPERIMENTAL +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Set the current MEMDB buffer +** EXPERIMENTAL +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnection from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +*/ +int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** EXPERIMENTAL +** +** The following are allowed values for the 6th argument (the "flags" or "F" +** argument) of the [sqlite3_deserialize()] interface. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ /* ** Undo the hack that converts floating point types to integer for diff --git a/src/tclsqlite.c b/src/tclsqlite.c index d02d94baf5..2c6e1bbe27 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1846,34 +1846,36 @@ static int SQLITE_TCLAPI DbObjCmd( int choice; int rc = TCL_OK; static const char *DB_strs[] = { - "authorizer", "backup", "busy", - "cache", "changes", "close", - "collate", "collation_needed", "commit_hook", - "complete", "copy", "enable_load_extension", - "errorcode", "eval", "exists", - "function", "incrblob", "interrupt", - "last_insert_rowid", "memdb", "nullvalue", - "onecolumn", "preupdate", "profile", - "progress", "rekey", "restore", - "rollback_hook", "status", "timeout", - "total_changes", "trace", "trace_v2", - "transaction", "unlock_notify", "update_hook", - "version", "wal_hook", 0 + "authorizer", "backup", "busy", + "cache", "changes", "close", + "collate", "collation_needed", "commit_hook", + "complete", "copy", "deserialize", + "enable_load_extension", "errorcode", "eval", + "exists", "function", "incrblob", + "interrupt", "last_insert_rowid", "memdb", + "nullvalue", "onecolumn", "preupdate", + "profile", "progress", "rekey", + "restore", "rollback_hook", "serialize", + "status", "timeout", "total_changes", + "trace", "trace_v2", "transaction", + "unlock_notify", "update_hook", "version", + "wal_hook", 0 }; enum DB_enum { - DB_AUTHORIZER, DB_BACKUP, DB_BUSY, - DB_CACHE, DB_CHANGES, DB_CLOSE, - DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, - DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, - DB_ERRORCODE, DB_EVAL, DB_EXISTS, - DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, - DB_LAST_INSERT_ROWID, DB_MEMDB, DB_NULLVALUE, - DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, - DB_PROGRESS, DB_REKEY, DB_RESTORE, - DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, - DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2, - DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, - DB_VERSION, DB_WAL_HOOK + DB_AUTHORIZER, DB_BACKUP, DB_BUSY, + DB_CACHE, DB_CHANGES, DB_CLOSE, + DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, + DB_COMPLETE, DB_COPY, DB_DESERIALIZE, + DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, + DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, + DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_MEMDB, + DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE, + DB_PROFILE, DB_PROGRESS, DB_REKEY, + DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE, + DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, + DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, + DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, + DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2411,6 +2413,16 @@ static int SQLITE_TCLAPI DbObjCmd( break; } + /* + ** $db deserialize ?DATABASE? VALUE + ** + ** Reopen DATABASE (default "main") using the content in $VALUE + */ + case DB_DESERIALIZE: { + rc = TCL_ERROR; /* TBD */ + break; + } + /* ** $db enable_load_extension BOOLEAN ** @@ -2679,17 +2691,8 @@ static int SQLITE_TCLAPI DbObjCmd( rc = TCL_ERROR; #else const char *zSchema = Tcl_GetString(objv[2]); - sqlite3_int64 sz = 0; unsigned char *pData; - if( objc==3 ){ - pData = sqlite3_memdb_ptr(pDb->db, zSchema, &sz); - if( pData==0 ){ - Tcl_AppendResult(interp, "not a MEMDB database", (char*)0); - rc = TCL_ERROR; - }else{ - Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz)); - } - }else if( objc==4 ){ + if( objc==4 ){ int len = 0, xrc; unsigned char *pBA = Tcl_GetByteArrayFromObj(objv[3], &len); pData = sqlite3_malloc64( len ); @@ -2933,6 +2936,39 @@ static int SQLITE_TCLAPI DbObjCmd( break; } + /* + ** $db serialize ?DATABASE? + ** + ** Return a serialization of a database. + */ + case DB_SERIALIZE: { +#ifndef SQLITE_ENABLE_MEMDB + Tcl_AppendResult(interp, "MEMDB not available in this build", + (char*)0); + rc = TCL_ERROR; +#else + const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main"; + sqlite3_int64 sz = 0; + unsigned char *pData; + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?"); + rc = TCL_ERROR; + }else{ + int needFree; + pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY); + if( pData ){ + needFree = 0; + }else{ + pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0); + needFree = 1; + } + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz)); + if( needFree ) sqlite3_free(pData); + } +#endif + break; + } + /* ** $db status (step|sort|autoindex|vmstep) ** diff --git a/test/memdb1.test b/test/memdb1.test index 13ef57ace4..36184e2e4e 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -27,8 +27,6 @@ ifcapable !memdb { # Verify that the size of $::db1 is the same as the size of # the database. # -db close -sqlite3 db dummy -vfs memdb unset -nocomplain db1 unset -nocomplain sz1 unset -nocomplain pgsz @@ -39,9 +37,12 @@ do_test 100 { } set ::pgsz [db one {PRAGMA page_size}] set ::sz1 [expr {$::pgsz*[db one {PRAGMA page_count}]}] - set ::db1 [db memdb main] + set ::db1 [db serialize] expr {[string length $::db1]==$::sz1} } 1 +set fd [open db1.db wb] +puts -nonewline $fd $db1 +close $fd # Create a new MEMDB and initialize it to the content of $::db1 # Verify that the content is the same. diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl index e3ddcb9eeb..88f645bbe3 100644 --- a/tool/mkopts.tcl +++ b/tool/mkopts.tcl @@ -11,7 +11,7 @@ while {![eof stdin]} { if {$line==""} continue regsub -all "\[ \t\n,\]+" [string trim $line] { } line foreach token [split $line { }] { - if {![regexp {(([a-zA-Z]+)_)?([_a-zA-Z]+)} $token all px p2 name]} continue + if {![regexp {(([a-zA-Z]+)_)?([_a-zA-Z0-9]+)} $token all px p2 name]} continue lappend namelist [string tolower $name] if {$px!=""} {set prefix $p2} } @@ -23,7 +23,7 @@ proc put_item x { global col if {$col==0} {puts -nonewline " "} if {$col<2} { - puts -nonewline [format " %-21s" $x] + puts -nonewline [format " %-25s" $x] incr col } else { puts $x From 3ec8665e22a6fe5cf6a2b98c04de1d350d519c8c Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 19:03:31 +0000 Subject: [PATCH 05/14] Replace sqlite3_memdb_config() with sqlite3_deserialize(). Remove the "db memdb" command from the TCL interface, replacing it with "db serialize" and "db deserialize". FossilOrigin-Name: 2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac --- manifest | 24 ++++---- manifest.uuid | 2 +- src/attach.c | 126 +++++++++++++++++++++++----------------- src/memdb.c | 99 ++++++++++++++++--------------- src/sqlite.h.in | 25 +------- src/sqliteInt.h | 5 +- src/tclsqlite.c | 138 ++++++++++++++++++-------------------------- test/memdb1.test | 3 +- test/tclsqlite.test | 2 +- 9 files changed, 203 insertions(+), 221 deletions(-) diff --git a/manifest b/manifest index 892a7572e4..cde71db315 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\sthe\ssqlite3_memdb_ptr()\sinterface\swith\sthe\smore\sgeneral\nsqlite3_serialize()\sinterface. -D 2018-01-03T16:49:52.676 +C Replace\ssqlite3_memdb_config()\swith\ssqlite3_deserialize().\s\sRemove\sthe\n"db\smemdb"\scommand\sfrom\sthe\sTCL\sinterface,\sreplacing\sit\swith\s"db\sserialize"\nand\s"db\sdeserialize". +D 2018-01-03T19:03:31.558 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -415,7 +415,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421 -F src/attach.c 84c477e856b24c2b9a0983b438a707c0cf4d616cee7a425401d418e58afec24c +F src/attach.c 52c34c2fb1a8852739aca3c4ae797f02660d826d1e79c067dadac97fe3335b6c F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -450,7 +450,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c 39dd9443f902759b858e598f17afc425c094b0d5f057b7ec988d224d812bd2a3 +F src/memdb.c 67c01e51b9e515721fbb4a27375233c67a8a8e5d66bd3fa6f4f84c85de43c05e F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -481,14 +481,14 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 -F src/sqlite.h.in 16bbb15a5fc53bfd725305ec9a201a7f57df7770749aa758b33a0636946d1bb4 +F src/sqlite.h.in 95a2e67c1ff46365eef3cb14e73d0b279a7435c0d0fb7e59c89cde9d4353dae2 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 2567341e37050ad542d57f3027b8717cb9b14ff363fdfeecf85421e0d973787f +F src/sqliteInt.h 713ee4be20beddf2f053b3ac1871c1f0d9ab54d1cc21c24a4365b560181b5d7d F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 322ad6b4e613aba84eee8cf6239eae668167f8b9891ca9e4aa53b78cd3aaff35 +F src/tclsqlite.c 8370ce15f97277304e7a17c47e18d47c1a31701fcd213eded727d09c547da2fc F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -1056,7 +1056,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test 062cdf3b7de2f861878e4275d3a67b80982d9f792f693418c844fade15ec7537 +F test/memdb1.test 6ae9f9fe51c918bf203ee5135f88d74f6e4446b573a9c07b141356f8f5fbeaf1 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1282,7 +1282,7 @@ F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 45462ee8dd0ca4fd95a476c9253d332ce2cf90985cb0ad5c7eae6e8c7fe24ae8 +F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6 F test/tempdb2.test 27e41ed540b2f9b056c2e77e9bddc1b875358507 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 47398ae77236a92f6b9345aa397361b6df127a9a2895c0771d506b0be10822b9 -R bfc121db68c7d1b10b977a508d74da37 +P 8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077 +R 752064346b8d3ad9381bcf73633be499 U drh -Z 6064e9ffbc398d82aebface075258c56 +Z 59a3fb5e3f8eae3c5ea078db9efbd371 diff --git a/manifest.uuid b/manifest.uuid index a6d77e2b7f..08b82513bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077 \ No newline at end of file +2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index fa38e84159..151b52e7a4 100644 --- a/src/attach.c +++ b/src/attach.c @@ -55,6 +55,10 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. +** +** If the db->init.reopenMemdb flags is set, then instead of attaching a +** new database, close the database on db->init.iDb and reopen it as an +** empty MemDB. */ static void attachFunc( sqlite3_context *context, @@ -75,65 +79,79 @@ static void attachFunc( sqlite3_vfs *pVfs; UNUSED_PARAMETER(NotUsed); - zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; - /* Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - for(i=0; inDb; i++){ - char *z = db->aDb[i].zDbSName; - assert( z && zName ); - if( sqlite3StrICmp(z, zName)==0 ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + if( db->init.reopenMemdb ){ + /* This is not a real ATTACH. Instead, this routine is being called + ** from sqlite3_deserialize() to close database db->init.iDb and + ** reopen it as a MemDB */ + pVfs = sqlite3_vfs_find("memdb"); + if( pVfs==0 ) return; + pNew = &db->aDb[db->init.iDb]; + sqlite3BtreeClose(pNew->pBt); + pNew->pBt = 0; + pNew->pSchema = 0; + rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + }else{ + /* This is a real ATTACH */ + + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); goto attach_error; } + for(i=0; inDb; i++){ + char *z = db->aDb[i].zDbSName; + assert( z && zName ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialize the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = aNew; + pNew = &db->aDb[db->nDb]; + memset(pNew, 0, sizeof(*pNew)); + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialized. + */ + flags = db->openFlags; + rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + assert( pVfs ); + flags |= SQLITE_OPEN_MAIN_DB; + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + sqlite3_free( zPath ); + db->nDb++; } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = aNew; - pNew = &db->aDb[db->nDb]; - memset(pNew, 0, sizeof(*pNew)); - - /* Open the database file. If the btree is successfully opened, use - ** it to obtain the database schema. At this point the schema may - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); - sqlite3_free( zPath ); - db->nDb++; db->skipBtreeMutex = 0; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; @@ -160,7 +178,7 @@ static void attachFunc( sqlite3BtreeLeave(pNew->pBt); } pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( !db->init.reopenMemdb ) pNew->zDbSName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -200,8 +218,8 @@ static void attachFunc( /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the way - ** we found it. + ** remove the entry from the db->aDb[] array. i.e. put everything back the + ** way we found it. */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); diff --git a/src/memdb.c b/src/memdb.c index 0a81978cce..5a1f12dcbb 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -12,17 +12,6 @@ ** ** This is an in-memory VFS implementation. The application supplies ** a chunk of memory to hold the database file. -** -** USAGE: -** -** sqlite3_open_v2("whatever", &db, SQLITE_OPEN_READWRITE, "memdb"); -** void *sqlite3_memdb_ptr(db, "main", &sz); -** int sqlite3_memdb_config(db, "main", pMem, szData, szMem, mFlags); -** -** Flags: -** -** SQLITE_MEMDB_FREEONCLOSE Free pMem when closing the connection -** SQLITE_MEMDB_RESIZEABLE Use sqlite3_realloc64() to resize pMem */ #ifdef SQLITE_ENABLE_MEMDB #include "sqliteInt.h" @@ -141,7 +130,7 @@ static const sqlite3_io_methods memdb_io_methods = { */ static int memdbClose(sqlite3_file *pFile){ MemFile *p = (MemFile *)pFile; - if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); + if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData); return SQLITE_OK; } @@ -169,7 +158,7 @@ static int memdbRead( */ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ unsigned char *pNew; - if( (p->mFlags & SQLITE_MEMDB_RESIZEABLE)==0 ) return SQLITE_FULL; + if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 ) return SQLITE_FULL; if( p->nMmap>0 ) return SQLITE_FULL; pNew = sqlite3_realloc64(p->aData, newSz); if( pNew==0 ) return SQLITE_FULL; @@ -334,7 +323,7 @@ static int memdbOpen( MemFile *p = (MemFile*)pFile; memset(p, 0, sizeof(*p)); if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN; - p->mFlags = SQLITE_MEMDB_RESIZEABLE | SQLITE_MEMDB_FREEONCLOSE; + p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; *pOutFlags = flags | SQLITE_OPEN_MEMORY; p->base.pMethods = &memdb_io_methods; return SQLITE_OK; @@ -450,37 +439,6 @@ static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ return p; } -/* -** Reconfigure a memdb database. -*/ -int sqlite3_memdb_config( - sqlite3 *db, - const char *zSchema, - void *aData, - sqlite3_int64 sz, - sqlite3_int64 szMax, - unsigned int mFlags -){ - MemFile *p = memdbFromDbSchema(db, zSchema); - int rc; - if( p==0 ){ - rc = SQLITE_ERROR; - }else if( p->eLock!=SQLITE_LOCK_NONE || p->nMmap>0 ){ - rc = SQLITE_BUSY; - }else{ - if( p->mFlags & SQLITE_MEMDB_FREEONCLOSE ) sqlite3_free(p->aData); - p->aData = aData; - p->sz = sz; - p->szMax = szMax; - p->mFlags = mFlags; - rc = SQLITE_OK; - } - if( rc!=SQLITE_OK && (mFlags & SQLITE_MEMDB_FREEONCLOSE)!=0 ){ - sqlite3_free(aData); - } - return SQLITE_OK; -} - /* ** Return the serialization of a database */ @@ -547,6 +505,57 @@ unsigned char *sqlite3_serialize( return pOut; } +/* Convert zSchema to a MemDB and initialize its content. +*/ +int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +){ + MemFile *p; + char *zSql; + sqlite3_stmt *pStmt = 0; + int rc; + int iDb; + + sqlite3_mutex_enter(db->mutex); + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + iDb = sqlite3FindDbName(db, zSchema); + if( iDb<0 ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ) goto end_deserialize; + db->init.iDb = (u8)iDb; + db->init.reopenMemdb = 1; + rc = sqlite3_step(pStmt); + db->init.reopenMemdb = 0; + if( rc!=SQLITE_DONE ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + p = memdbFromDbSchema(db, zSchema); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + p->aData = pData; + p->sz = szDb; + p->szMax = szBuf; + p->mFlags = mFlags; + rc = SQLITE_OK; + } +end_deserialize: + sqlite3_finalize(pStmt); + sqlite3_mutex_leave(db->mutex); + return rc; +} + /* ** This routine is called when the extension is loaded. ** Register the new VFS. diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 6b6a5655b3..233a2cf60e 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8758,29 +8758,6 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); -/* -** CAPI3REF: Set the current MEMDB buffer -** EXPERIMENTAL -** -** This interface is only available when SQLite is compiled -** with SQLITE_ENABLE_MEMDB. -** -** The sqlite3_memdb_config(D,S,P,N,M,F) interface initializes a MEMDB database. -** The database identified by D and S must not be in active use when this -** interface is called, or [SQLITE_BUSY] is returned. -*/ -int sqlite3_memdb_config(sqlite3*,const char*,void*,sqlite3_int64,sqlite3_int64,unsigned); - -/* -** CAPI3REF: Flags for configuring MEMDB databases -** EXPERIMENTAL -** -** The following are allowed values for the 6th argument (the "flags" -** argument) of the [sqlite3_memdb_config()] interface. -*/ -#define SQLITE_MEMDB_FREEONCLOSE 0x001 /* Free the memory buffer on close */ -#define SQLITE_MEMDB_RESIZEABLE 0x002 /* Resize using sqlite3_realloc64() */ - /* ** CAPI3REF: Serialize a database ** EXPERIMENTAL @@ -8829,7 +8806,7 @@ unsigned char *sqlite3_serialize( #define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ /* -** CAPI3REF: Set the current MEMDB buffer +** CAPI3REF: Deserialize a database ** EXPERIMENTAL ** ** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 002fb4e916..35074ee81a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1365,8 +1365,9 @@ struct sqlite3 { int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ - u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ - u8 imposterTable; /* Building an imposter table */ + u8 orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ + u8 imposterTable : 1; /* Building an imposter table */ + u8 reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 2c6e1bbe27..c9b4ff6107 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1852,14 +1852,14 @@ static int SQLITE_TCLAPI DbObjCmd( "complete", "copy", "deserialize", "enable_load_extension", "errorcode", "eval", "exists", "function", "incrblob", - "interrupt", "last_insert_rowid", "memdb", - "nullvalue", "onecolumn", "preupdate", - "profile", "progress", "rekey", - "restore", "rollback_hook", "serialize", - "status", "timeout", "total_changes", - "trace", "trace_v2", "transaction", - "unlock_notify", "update_hook", "version", - "wal_hook", 0 + "interrupt", "last_insert_rowid", "nullvalue", + "onecolumn", "preupdate", "profile", + "progress", "rekey", "restore", + "rollback_hook", "serialize", "status", + "timeout", "total_changes", "trace", + "trace_v2", "transaction", "unlock_notify", + "update_hook", "version", "wal_hook", + 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BUSY, @@ -1868,14 +1868,13 @@ static int SQLITE_TCLAPI DbObjCmd( DB_COMPLETE, DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, - DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_MEMDB, - DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE, - DB_PROFILE, DB_PROGRESS, DB_REKEY, - DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE, - DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, - DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, - DB_WAL_HOOK + DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, + DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, + DB_PROGRESS, DB_REKEY, DB_RESTORE, + DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS, + DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, + DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY, + DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2419,7 +2418,44 @@ static int SQLITE_TCLAPI DbObjCmd( ** Reopen DATABASE (default "main") using the content in $VALUE */ case DB_DESERIALIZE: { - rc = TCL_ERROR; /* TBD */ +#ifndef SQLITE_ENABLE_MEMDB + Tcl_AppendResult(interp, "MEMDB not available in this build", + (char*)0); + rc = TCL_ERROR; +#else + const char *zSchema; + Tcl_Obj *pValue; + unsigned char *pBA; + unsigned char *pData; + int len, xrc; + + if( objc==3 ){ + zSchema = 0; + pValue = objv[2]; + }else if( objc==4 ){ + zSchema = Tcl_GetString(objv[2]); + pValue = objv[3]; + }else{ + Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE"); + rc = TCL_ERROR; + break; + } + pBA = Tcl_GetByteArrayFromObj(pValue, &len); + pData = sqlite3_malloc64( len ); + if( pData==0 ){ + Tcl_AppendResult(interp, "out of memory", (char*)0); + rc = TCL_ERROR; + }else{ + memcpy(pData, pBA, len); + xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, + SQLITE_DESERIALIZE_FREEONCLOSE | + SQLITE_DESERIALIZE_RESIZEABLE); + if( xrc ){ + Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); + rc = TCL_ERROR; + } + } +#endif break; } @@ -2678,44 +2714,6 @@ static int SQLITE_TCLAPI DbObjCmd( break; } - /* - ** $db memdb DATABASE ?BLOB? - ** - ** Set or query the content of a MEMDB database. - ** - */ - case DB_MEMDB: { -#ifndef SQLITE_ENABLE_MEMDB - Tcl_AppendResult(interp, "MEMDB not available in this build", - (char*)0); - rc = TCL_ERROR; -#else - const char *zSchema = Tcl_GetString(objv[2]); - unsigned char *pData; - if( objc==4 ){ - int len = 0, xrc; - unsigned char *pBA = Tcl_GetByteArrayFromObj(objv[3], &len); - pData = sqlite3_malloc64( len ); - if( pData==0 ){ - Tcl_AppendResult(interp, "out of memory", (char*)0); - rc = TCL_ERROR; - }else{ - memcpy(pData, pBA, len); - xrc = sqlite3_memdb_config(pDb->db, zSchema, pData, len, len, - SQLITE_MEMDB_FREEONCLOSE|SQLITE_MEMDB_RESIZEABLE); - if( xrc ){ - Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); - rc = TCL_ERROR; - } - } - }else{ - Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); - rc = TCL_ERROR; - } -#endif - break; - } - /* ** $db nullvalue ?STRING? ** @@ -3481,9 +3479,6 @@ static int SQLITE_TCLAPI DbMain( int nKey = 0; #endif int rc; -#ifdef SQLITE_ENABLE_MEMDB - Tcl_Obj *pDbObj = 0; -#endif /* In normal use, each TCL interpreter runs in a single thread. So ** by default, we can turn off mutexing on SQLite database connections. @@ -3576,10 +3571,6 @@ static int SQLITE_TCLAPI DbMain( }else{ flags &= ~SQLITE_OPEN_URI; } -#ifdef SQLITE_ENABLE_MEMDB - }else if( strcmp(zArg, "-memdb")==0 ){ - pDbObj = objv[i]; -#endif }else{ Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0); return TCL_ERROR; @@ -3588,25 +3579,10 @@ static int SQLITE_TCLAPI DbMain( zErrMsg = 0; p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); memset(p, 0, sizeof(*p)); -#ifdef SQLITE_ENABLE_MEMDB - if( pDbObj ){ - rc = sqlite3_open_v2("x", &p->db, flags, "memdb"); - if( rc==SQLITE_OK ){ - int len; - unsigned char *aData = Tcl_GetByteArrayFromObj(pDbObj, &len); - unsigned char *a = sqlite3_malloc64( len ); - memcpy(a, aData, len); - sqlite3_memdb_config(p->db, "main", a, len, sqlite3_msize(a), - SQLITE_MEMDB_FREEONCLOSE | SQLITE_MEMDB_RESIZEABLE); - } - }else -#endif - { - if( zFile==0 ) zFile = ":memory:"; - zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); - rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); - Tcl_DStringFree(&translatedFilename); - } + if( zFile==0 ) zFile = ""; + zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); + rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); + Tcl_DStringFree(&translatedFilename); if( p->db ){ if( SQLITE_OK!=sqlite3_errcode(p->db) ){ zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); diff --git a/test/memdb1.test b/test/memdb1.test index 36184e2e4e..c37cac2664 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -48,7 +48,8 @@ close $fd # Verify that the content is the same. # db close -sqlite3 db -memdb $db1 +sqlite3 db +db deserialize $db1 do_execsql_test 110 { SELECT * FROM t1; } {1 2} diff --git a/test/tclsqlite.test b/test/tclsqlite.test index ca53710ec2..fb4be3dfcb 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -34,7 +34,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, memdb, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg From 99abe5c478d5340616bc9418f7fd7c07b33dedfe Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 22:48:38 +0000 Subject: [PATCH 06/14] Miscellaneous code and comment cleanup. FossilOrigin-Name: fa6069fb3b0a4411fd6661dec7de40ece3064a2fe4b94ebfbda9e5e524e04e86 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/attach.c | 18 ++++++++++++------ src/memdb.c | 45 +++++++++------------------------------------ 4 files changed, 29 insertions(+), 50 deletions(-) diff --git a/manifest b/manifest index cde71db315..4f22c2b67d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Replace\ssqlite3_memdb_config()\swith\ssqlite3_deserialize().\s\sRemove\sthe\n"db\smemdb"\scommand\sfrom\sthe\sTCL\sinterface,\sreplacing\sit\swith\s"db\sserialize"\nand\s"db\sdeserialize". -D 2018-01-03T19:03:31.558 +C Miscellaneous\scode\sand\scomment\scleanup. +D 2018-01-03T22:48:38.759 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -415,7 +415,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421 -F src/attach.c 52c34c2fb1a8852739aca3c4ae797f02660d826d1e79c067dadac97fe3335b6c +F src/attach.c af582a55cdb0435dc21da926cfcd5545eadfd99ea201b5b9e067cbeae1077077 F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -450,7 +450,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c 67c01e51b9e515721fbb4a27375233c67a8a8e5d66bd3fa6f4f84c85de43c05e +F src/memdb.c d58bb51e6029a7bd91b2148b98ab00c3a271c6cd2632eb756cfcd91e1252930b F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077 -R 752064346b8d3ad9381bcf73633be499 +P 2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac +R bb0359f4210b8aee0e32802f6ef52a4c U drh -Z 59a3fb5e3f8eae3c5ea078db9efbd371 +Z c49fae41835e3bd8d0d8eeb0cf1f4a88 diff --git a/manifest.uuid b/manifest.uuid index 08b82513bb..cf39388ce7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac \ No newline at end of file +fa6069fb3b0a4411fd6661dec7de40ece3064a2fe4b94ebfbda9e5e524e04e86 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 151b52e7a4..f177f1a5b5 100644 --- a/src/attach.c +++ b/src/attach.c @@ -84,7 +84,13 @@ static void attachFunc( if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; - if( db->init.reopenMemdb ){ +#ifdef SQLITE_ENABLE_MEMDB +# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) +#else +# define REOPEN_AS_MEMDB(db) (0) +#endif + + if( REOPEN_AS_MEMDB(db) ){ /* This is not a real ATTACH. Instead, this routine is being called ** from sqlite3_deserialize() to close database db->init.iDb and ** reopen it as a MemDB */ @@ -96,9 +102,9 @@ static void attachFunc( pNew->pSchema = 0; rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); }else{ - /* This is a real ATTACH */ - - /* Check for the following errors: + /* This is a real ATTACH + ** + ** Check for the following errors: ** ** * Too many attached databases, ** * Transaction currently open @@ -178,7 +184,7 @@ static void attachFunc( sqlite3BtreeLeave(pNew->pBt); } pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - if( !db->init.reopenMemdb ) pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -235,7 +241,7 @@ static void attachFunc( } } #endif - if( rc ){ + if( rc && !REOPEN_AS_MEMDB(db) ){ int iDb = db->nDb - 1; assert( iDb>=2 ); if( db->aDb[iDb].pBt ){ diff --git a/src/memdb.c b/src/memdb.c index 5a1f12dcbb..5aa66f1fde 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -10,8 +10,11 @@ ** ****************************************************************************** ** -** This is an in-memory VFS implementation. The application supplies -** a chunk of memory to hold the database file. +** This file implements in-memory VFS. A database is held as a contiguous +** block of memory. +** +** This file also implements interface sqlite3_serialize() and +** sqlite3_deserialize(). */ #ifdef SQLITE_ENABLE_MEMDB #include "sqliteInt.h" @@ -52,10 +55,6 @@ static int memdbCheckReservedLock(sqlite3_file*, int *pResOut); static int memdbFileControl(sqlite3_file*, int op, void *pArg); static int memdbSectorSize(sqlite3_file*); static int memdbDeviceCharacteristics(sqlite3_file*); -static int memdbShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**); -static int memdbShmLock(sqlite3_file*, int offset, int n, int flags); -static void memdbShmBarrier(sqlite3_file*); -static int memdbShmUnmap(sqlite3_file*, int deleteFlag); static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); @@ -112,10 +111,10 @@ static const sqlite3_io_methods memdb_io_methods = { memdbFileControl, /* xFileControl */ memdbSectorSize, /* xSectorSize */ memdbDeviceCharacteristics, /* xDeviceCharacteristics */ - memdbShmMap, /* xShmMap */ - memdbShmLock, /* xShmLock */ - memdbShmBarrier, /* xShmBarrier */ - memdbShmUnmap, /* xShmUnmap */ + 0, /* xShmMap */ + 0, /* xShmLock */ + 0, /* xShmBarrier */ + 0, /* xShmUnmap */ memdbFetch, /* xFetch */ memdbUnfetch /* xUnfetch */ }; @@ -264,32 +263,6 @@ static int memdbDeviceCharacteristics(sqlite3_file *pFile){ SQLITE_IOCAP_SEQUENTIAL; } -/* Create a shared memory file mapping */ -static int memdbShmMap( - sqlite3_file *pFile, - int iPg, - int pgsz, - int bExtend, - void volatile **pp -){ - return SQLITE_IOERR_SHMMAP; -} - -/* Perform locking on a shared-memory segment */ -static int memdbShmLock(sqlite3_file *pFile, int offset, int n, int flags){ - return SQLITE_IOERR_SHMLOCK; -} - -/* Memory barrier operation on shared memory */ -static void memdbShmBarrier(sqlite3_file *pFile){ - return; -} - -/* Unmap a shared memory segment */ -static int memdbShmUnmap(sqlite3_file *pFile, int deleteFlag){ - return SQLITE_OK; -} - /* Fetch a page of a memory-mapped file */ static int memdbFetch( sqlite3_file *pFile, From a5bb43518b406098d4545c98fcffc80724c9f1fc Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 23:40:02 +0000 Subject: [PATCH 07/14] New test cases and fixes for minor problems. FossilOrigin-Name: e0da2cc382e0db33d0423372133115f52c77bd0093dbf816c7e88a0aad5f6582 --- manifest | 16 ++++---- manifest.uuid | 2 +- src/attach.c | 1 + src/tclsqlite.c | 4 +- test/memdb1.test | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 4f22c2b67d..77a6b3f324 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Miscellaneous\scode\sand\scomment\scleanup. -D 2018-01-03T22:48:38.759 +C New\stest\scases\sand\sfixes\sfor\sminor\sproblems. +D 2018-01-03T23:40:02.979 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -415,7 +415,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421 -F src/attach.c af582a55cdb0435dc21da926cfcd5545eadfd99ea201b5b9e067cbeae1077077 +F src/attach.c 8158394251d62a6513d6e395f14c9b8ad3f3447d8a1249c242c940cde5c1453e F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -488,7 +488,7 @@ F src/sqliteInt.h 713ee4be20beddf2f053b3ac1871c1f0d9ab54d1cc21c24a4365b560181b5d F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 8370ce15f97277304e7a17c47e18d47c1a31701fcd213eded727d09c547da2fc +F src/tclsqlite.c 4f4ca19af1a666da6f80d35443e58905d1fb7cbdb9899cf9ce7da60aeede5830 F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -1056,7 +1056,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test 6ae9f9fe51c918bf203ee5135f88d74f6e4446b573a9c07b141356f8f5fbeaf1 +F test/memdb1.test 526252d466ecc3701550000651e1405d08ccefe0bf23e2dc86ada90e81a8eacc F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac -R bb0359f4210b8aee0e32802f6ef52a4c +P fa6069fb3b0a4411fd6661dec7de40ece3064a2fe4b94ebfbda9e5e524e04e86 +R 80c4d802a2eb305cbf9b2f9ece314afe U drh -Z c49fae41835e3bd8d0d8eeb0cf1f4a88 +Z e7e409e5145088df0792d1925f4056dd diff --git a/manifest.uuid b/manifest.uuid index cf39388ce7..069635c8d7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa6069fb3b0a4411fd6661dec7de40ece3064a2fe4b94ebfbda9e5e524e04e86 \ No newline at end of file +e0da2cc382e0db33d0423372133115f52c77bd0093dbf816c7e88a0aad5f6582 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index f177f1a5b5..597351fa39 100644 --- a/src/attach.c +++ b/src/attach.c @@ -229,6 +229,7 @@ static void attachFunc( */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); + db->init.iDb = 0; rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); } diff --git a/src/tclsqlite.c b/src/tclsqlite.c index c9b4ff6107..f3261d1e79 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2442,11 +2442,11 @@ static int SQLITE_TCLAPI DbObjCmd( } pBA = Tcl_GetByteArrayFromObj(pValue, &len); pData = sqlite3_malloc64( len ); - if( pData==0 ){ + if( pData==0 && len>0 ){ Tcl_AppendResult(interp, "out of memory", (char*)0); rc = TCL_ERROR; }else{ - memcpy(pData, pBA, len); + if( len>0 ) memcpy(pData, pBA, len); xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE); diff --git a/test/memdb1.test b/test/memdb1.test index c37cac2664..48f9fca5ec 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -54,5 +54,109 @@ do_execsql_test 110 { SELECT * FROM t1; } {1 2} +# What happens when we try to VACUUM a MEMDB database? +# +do_execsql_test 120 { + VACUUM; +} {} +do_execsql_test 130 { + CREATE TABLE t2(x, y); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t2(x, y) SELECT x, randomblob(1000) FROM c; + DROP TABLE t2; + PRAGMA page_count; +} {116} +do_execsql_test 140 { + VACUUM; + PRAGMA page_count; +} {2} + +# Build a largish on-disk database and serialize it. Verify that the +# serialization works. +# +db close +forcedelete test.db +sqlite3 db test.db +do_execsql_test 200 { + CREATE TABLE t3(x, y); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400) + INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c; + PRAGMA quick_check; +} {ok} +set fd [open test.db rb] +unset -nocomplain direct +set direct [read $fd] +close $fd +do_test 210 { + string length [db serialize] +} [string length $direct] +do_test 220 { + db eval {ATTACH ':memory:' AS aux1} + db deserialize aux1 $::direct + db eval { + SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3; + } +} {} +unset -nocomplain direct + +# Do the same with a :memory: database. +# +db close +sqlite3 db :memory: +do_execsql_test 300 { + CREATE TABLE t3(x, y); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400) + INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c; + PRAGMA quick_check; +} {ok} +do_test 310 { + db eval {ATTACH ':memory:' AS aux1} + db deserialize aux1 [db serialize main] + db eval { + SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3; + } +} {} + +# Deserialize an empty database +# +db close +sqlite3 db +db deserialize {} +do_execsql_test 400 { + PRAGMA integrity_check; +} {ok} +do_execsql_test 410 { + CREATE TABLE t4(a,b); + INSERT INTO t4 VALUES('hello','world!'); + PRAGMA integrity_check; + SELECT * FROM t4; +} {ok hello world!} + +# Deserialize something that is not a database. +# +db close +sqlite3 db +do_test 500 { + set rc [catch {db deserialize not-a-database} msg] + lappend rc $msg +} {0 {}} +do_catchsql_test 510 { + PRAGMA integrity_check; +} {1 {file is not a database}} + +# Abuse the serialize and deserialize commands. Make sure errors are caught. +# +do_test 600 { + set rc [catch {db deserialize} msg] + lappend rc $msg +} {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}} +do_test 610 { + set rc [catch {db deserialize a b c} msg] + lappend rc $msg +} {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}} +do_test 620 { + set rc [catch {db serialize a b} msg] + lappend rc $msg +} {1 {wrong # args: should be "db serialize ?DATABASE?"}} finish_test From e616735cb190447097b83af23734dafd9fcda548 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 23:54:18 +0000 Subject: [PATCH 08/14] Fix compiler warnings on Windows. FossilOrigin-Name: 512b8e40c4ce2066d230b5f007bd704dc3577e21c55131ef07d90bf2fcf91b40 --- ext/misc/unionvtab.c | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c.in | 2 +- src/sqliteInt.h | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ext/misc/unionvtab.c b/ext/misc/unionvtab.c index 14cce84510..92d0b833c4 100644 --- a/ext/misc/unionvtab.c +++ b/ext/misc/unionvtab.c @@ -799,7 +799,7 @@ static void unionConfigureVtab( zVal = zOpt; if( *zVal==':' ) zVal++; while( union_isidchar(*zVal) ) zVal++; - nOpt = zVal-zOpt; + nOpt = (int)(zVal-zOpt); while( union_isspace(*zVal) ) zVal++; if( *zVal=='=' ){ diff --git a/manifest b/manifest index 77a6b3f324..29c6ed4690 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stest\scases\sand\sfixes\sfor\sminor\sproblems. -D 2018-01-03T23:40:02.979 +C Fix\scompiler\swarnings\son\sWindows. +D 2018-01-03T23:54:18.421 F Makefile.in 892bf253c48f3d2d8d4e4e89b44b71aa548a0eba11b148c338690cfb99822859 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 3b7ee2ebaf579fe7d30bece93e61e52782c3ff836455cba3a192f7a8f6f269d6 @@ -293,7 +293,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 F ext/misc/spellfix.c 41cf26c6b89fcaa8798ae10ae64d39c1f1d9d6995152e545bd491c13058b8fac F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 -F ext/misc/unionvtab.c de36c2c45583d68f99e45b392311967066b02e2651d05697da783698b245b387 +F ext/misc/unionvtab.c 2aa94902ea646e1aaf6c05eac944a14276cddd67735b2ad856030ffffbb6626c F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178 F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9 @@ -480,11 +480,11 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 +F src/shell.c.in 23b0207a222c1a1fcd0a3b9d790c79c0713212d63be94d96c0be0e62ccac3cd0 F src/sqlite.h.in 95a2e67c1ff46365eef3cb14e73d0b279a7435c0d0fb7e59c89cde9d4353dae2 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 713ee4be20beddf2f053b3ac1871c1f0d9ab54d1cc21c24a4365b560181b5d7d +F src/sqliteInt.h 315d863d61ac951d125934bc0946db15e94c61890d93fd6c6ff29c3c9881b39c F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1690,7 +1690,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fa6069fb3b0a4411fd6661dec7de40ece3064a2fe4b94ebfbda9e5e524e04e86 -R 80c4d802a2eb305cbf9b2f9ece314afe +P e0da2cc382e0db33d0423372133115f52c77bd0093dbf816c7e88a0aad5f6582 +R 3114b544cf591fa5de64b7bed571adcc U drh -Z e7e409e5145088df0792d1925f4056dd +Z b9d8faa03d64775d21ab162e0db38bba diff --git a/manifest.uuid b/manifest.uuid index 069635c8d7..e191c40967 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0da2cc382e0db33d0423372133115f52c77bd0093dbf816c7e88a0aad5f6582 \ No newline at end of file +512b8e40c4ce2066d230b5f007bd704dc3577e21c55131ef07d90bf2fcf91b40 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 4c9e60769a..1421ab4199 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4272,7 +4272,7 @@ static int expertDotCommand( char *z = azArg[i]; int n; if( z[0]=='-' && z[1]=='-' ) z++; - n = strlen(z); + n = strlen30(z); if( n>=2 && 0==strncmp(z, "-verbose", n) ){ pState->expert.bVerbose = 1; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 35074ee81a..757cfcb994 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1365,9 +1365,9 @@ struct sqlite3 { int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ - u8 orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ - u8 imposterTable : 1; /* Building an imposter table */ - u8 reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ + unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ + unsigned imposterTable : 1; /* Building an imposter table */ + unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ From b2194cea4ef650935e1b2bc0ea611d295e2eade4 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 1 Mar 2018 22:18:26 +0000 Subject: [PATCH 09/14] Allow the zSchema argument to sqlite3_serialize() to be NULL to mean the main database. FossilOrigin-Name: 5b01b9914fb612ceece34f40d45c7eb97c3504fc5a0a5ff0e67120bdee67f6ee --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memdb.c | 7 +++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 737fe75fb0..ad80e19ef4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\senhancements\sfrom\strunk. -D 2018-03-01T13:44:40.762 +C Allow\sthe\szSchema\sargument\sto\ssqlite3_serialize()\sto\sbe\sNULL\sto\smean\sthe\nmain\sdatabase. +D 2018-03-01T22:18:26.726 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -460,7 +460,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c d58bb51e6029a7bd91b2148b98ab00c3a271c6cd2632eb756cfcd91e1252930b +F src/memdb.c f01e30a224d22e0487bf42028249d09ddccfed18ac03002d24b70a832d53ac1e F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6ef3de810d54563c227045b16197b8011ce285ea867261946f93b2de55344f29 745a9a7fef0f28a57ea3f44899058993f6ecdedda52c81a09a4a9ce09c9004d6 -R 130ade233524cab0a0641e76e7f210be +P c8083de14b54fba1071385f8530d03d5684efd4963fde0f83ddc53ae3118a75b +R 4b7ab64dd9b0ddcbf834b7f0ea1bb2ba U drh -Z 8606a5979f84a0a30cbed3690217d5a2 +Z fef65347c0470682ba0a8e9f51beb02d diff --git a/manifest.uuid b/manifest.uuid index cfa0aa6b38..a69ed8658a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c8083de14b54fba1071385f8530d03d5684efd4963fde0f83ddc53ae3118a75b \ No newline at end of file +5b01b9914fb612ceece34f40d45c7eb97c3504fc5a0a5ff0e67120bdee67f6ee \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index 5aa66f1fde..24c676e75d 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -421,8 +421,8 @@ unsigned char *sqlite3_serialize( sqlite3_int64 *piSize, /* Write size here, if not NULL */ unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ ){ - MemFile *p = memdbFromDbSchema(db, zSchema); - int iDb = sqlite3FindDbName(db, zSchema); + MemFile *p; + int iDb; Btree *pBt; sqlite3_int64 sz; int szPage = 0; @@ -431,6 +431,9 @@ unsigned char *sqlite3_serialize( char *zSql; int rc; + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + p = memdbFromDbSchema(db, zSchema); + iDb = sqlite3FindDbName(db, zSchema); if( piSize ) *piSize = -1; if( iDb<0 ) return 0; if( p ){ From 5f9d192de9a336f8bb3ed63181cf190d06c60ee0 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 6 Mar 2018 04:01:08 +0000 Subject: [PATCH 10/14] Improvements to the memdb VFS. FossilOrigin-Name: a14fed69d0d4932fc6c71cf8acc5199cca4efbd10bca563a8e86038d6afd5c64 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memdb.c | 38 ++++++++++++++++++++++++++------------ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 0daa75ee51..3dabf8b492 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\swalIteratorInit()\sfix\sfrom\strunk. -D 2018-03-06T02:00:20.576 +C Improvements\sto\sthe\smemdb\sVFS. +D 2018-03-06T04:01:08.317 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -460,7 +460,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c f01e30a224d22e0487bf42028249d09ddccfed18ac03002d24b70a832d53ac1e +F src/memdb.c a559d61e55a715ec48b48685d20431fde1e114fb4df689df89334cedf4c0101c F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6274cf1f397d36be9e9b65b1935a776c834e4512e0e89f82c132efd4d1e8ef82 e5ce256aa1f7a8ae995b79c9da895827bee5d8d0724fc15413ff203dc9e2602d -R 4fdec0179640fc276902d16463f8cb6d +P 6399e101d5f6b8582640e0d90783e56042eaa1600db3bd02f8df5e7b01ac1cab +R 308fbe14b615cda601b7af6fc89baf23 U drh -Z bbb52f4afaed03841603241952a4da37 +Z b79ee0d17ceeeb3759cd662f53a7e6c2 diff --git a/manifest.uuid b/manifest.uuid index 854da70375..bbe7322aa5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6399e101d5f6b8582640e0d90783e56042eaa1600db3bd02f8df5e7b01ac1cab \ No newline at end of file +a14fed69d0d4932fc6c71cf8acc5199cca4efbd10bca563a8e86038d6afd5c64 \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index 24c676e75d..ec917e776b 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -53,7 +53,7 @@ static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); static int memdbLock(sqlite3_file*, int); static int memdbCheckReservedLock(sqlite3_file*, int *pResOut); static int memdbFileControl(sqlite3_file*, int op, void *pArg); -static int memdbSectorSize(sqlite3_file*); +/* static int memdbSectorSize(sqlite3_file*); // not used */ static int memdbDeviceCharacteristics(sqlite3_file*); static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); @@ -109,7 +109,7 @@ static const sqlite3_io_methods memdb_io_methods = { memdbLock, /* xUnlock - same as xLock in this case */ memdbCheckReservedLock, /* xCheckReservedLock */ memdbFileControl, /* xFileControl */ - memdbSectorSize, /* xSectorSize */ + 0, /* memdbSectorSize,*/ /* xSectorSize */ memdbDeviceCharacteristics, /* xDeviceCharacteristics */ 0, /* xShmMap */ 0, /* xShmLock */ @@ -157,10 +157,11 @@ static int memdbRead( */ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ unsigned char *pNew; - if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 ) return SQLITE_FULL; - if( p->nMmap>0 ) return SQLITE_FULL; + if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){ + return SQLITE_FULL; + } pNew = sqlite3_realloc64(p->aData, newSz); - if( pNew==0 ) return SQLITE_FULL; + if( pNew==0 ) return SQLITE_NOMEM; p->aData = pNew; p->szMax = newSz; return SQLITE_OK; @@ -177,8 +178,11 @@ static int memdbWrite( ){ MemFile *p = (MemFile *)pFile; if( iOfst+iAmt>p->sz ){ - if( iOfst+iAmt>p->szMax && memdbEnlarge(p, (iOfst+iAmt)*2) ){ - return SQLITE_FULL; + int rc; + if( iOfst+iAmt>p->szMax + && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK + ){ + return rc; } if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); p->sz = iOfst+iAmt; @@ -193,7 +197,10 @@ static int memdbWrite( static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ MemFile *p = (MemFile *)pFile; if( size>p->sz ){ - if( size>p->szMax && memdbEnlarge(p, size) ) return SQLITE_FULL; + int rc; + if( size>p->szMax && (rc = memdbEnlarge(p, size))!=SQLITE_OK ){ + return rc; + } memset(p->aData+p->sz, 0, size-p->sz); } p->sz = size; @@ -246,12 +253,14 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ return rc; } +#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ /* ** Return the sector-size in bytes for an memdb-file. */ static int memdbSectorSize(sqlite3_file *pFile){ return 1024; } +#endif /* ** Return the device characteristic flags supported by an memdb-file. @@ -294,10 +303,12 @@ static int memdbOpen( int *pOutFlags ){ MemFile *p = (MemFile*)pFile; + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ + return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags); + } memset(p, 0, sizeof(*p)); - if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN; p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; - *pOutFlags = flags | SQLITE_OPEN_MEMORY; + if( pOutFlags ) *pOutFlags = flags | SQLITE_OPEN_MEMORY; p->base.pMethods = &memdb_io_methods; return SQLITE_OK; } @@ -537,8 +548,11 @@ end_deserialize: ** Register the new VFS. */ int sqlite3MemdbInit(void){ - memdb_vfs.pAppData = sqlite3_vfs_find(0); - memdb_vfs.szOsFile = sizeof(MemFile); + sqlite3_vfs *pLower = sqlite3_vfs_find(0); + int sz = pLower->szOsFile; + memdb_vfs.pAppData = pLower; + if( sz Date: Tue, 6 Mar 2018 19:14:32 +0000 Subject: [PATCH 11/14] Simplifications to the memdb VFS. FossilOrigin-Name: 6c3f723a6856fa38ea3f11a36b56f46c5c1fcf17f4daf712e5e0b42562d5f4c6 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memdb.c | 54 +++++++++++++++++++++++++++++---------------------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 3dabf8b492..f599a85e45 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\smemdb\sVFS. -D 2018-03-06T04:01:08.317 +C Simplifications\sto\sthe\smemdb\sVFS. +D 2018-03-06T19:14:32.801 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -460,7 +460,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c a559d61e55a715ec48b48685d20431fde1e114fb4df689df89334cedf4c0101c +F src/memdb.c ffdca40946f9cff49c6d0f452648233d1a5234bb1dfa456787ee82333164d126 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6399e101d5f6b8582640e0d90783e56042eaa1600db3bd02f8df5e7b01ac1cab -R 308fbe14b615cda601b7af6fc89baf23 +P a14fed69d0d4932fc6c71cf8acc5199cca4efbd10bca563a8e86038d6afd5c64 +R b9fff9a384a4ae44f14923e3716823bc U drh -Z b79ee0d17ceeeb3759cd662f53a7e6c2 +Z ed8ab2a467fe746aa3cc4991867879e0 diff --git a/manifest.uuid b/manifest.uuid index bbe7322aa5..77b67bccf4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a14fed69d0d4932fc6c71cf8acc5199cca4efbd10bca563a8e86038d6afd5c64 \ No newline at end of file +6c3f723a6856fa38ea3f11a36b56f46c5c1fcf17f4daf712e5e0b42562d5f4c6 \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index ec917e776b..b2eefde955 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -51,7 +51,7 @@ static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); static int memdbSync(sqlite3_file*, int flags); static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); static int memdbLock(sqlite3_file*, int); -static int memdbCheckReservedLock(sqlite3_file*, int *pResOut); +/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ static int memdbFileControl(sqlite3_file*, int op, void *pArg); /* static int memdbSectorSize(sqlite3_file*); // not used */ static int memdbDeviceCharacteristics(sqlite3_file*); @@ -62,7 +62,7 @@ static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); ** Methods for MemVfs */ static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); +/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); @@ -71,7 +71,7 @@ static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); static void memdbDlClose(sqlite3_vfs*, void*); static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); static int memdbSleep(sqlite3_vfs*, int microseconds); -static int memdbCurrentTime(sqlite3_vfs*, double*); +/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ static int memdbGetLastError(sqlite3_vfs*, int, char *); static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); @@ -83,7 +83,7 @@ static sqlite3_vfs memdb_vfs = { "memdb", /* zName */ 0, /* pAppData (set when registered) */ memdbOpen, /* xOpen */ - memdbDelete, /* xDelete */ + 0, /* memdbDelete, */ /* xDelete */ memdbAccess, /* xAccess */ memdbFullPathname, /* xFullPathname */ memdbDlOpen, /* xDlOpen */ @@ -92,7 +92,7 @@ static sqlite3_vfs memdb_vfs = { memdbDlClose, /* xDlClose */ memdbRandomness, /* xRandomness */ memdbSleep, /* xSleep */ - memdbCurrentTime, /* xCurrentTime */ + 0, /* memdbCurrentTime, */ /* xCurrentTime */ memdbGetLastError, /* xGetLastError */ memdbCurrentTimeInt64 /* xCurrentTimeInt64 */ }; @@ -107,7 +107,7 @@ static const sqlite3_io_methods memdb_io_methods = { memdbFileSize, /* xFileSize */ memdbLock, /* xLock */ memdbLock, /* xUnlock - same as xLock in this case */ - memdbCheckReservedLock, /* xCheckReservedLock */ + 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ memdbFileControl, /* xFileControl */ 0, /* memdbSectorSize,*/ /* xSectorSize */ memdbDeviceCharacteristics, /* xDeviceCharacteristics */ @@ -193,16 +193,14 @@ static int memdbWrite( /* ** Truncate an memdb-file. +** +** In rollback mode (which is always the case for memdb, as it does not +** support WAL mode) the truncate() method is only used to reduce +** the size of a file, never to increase the size. */ static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ MemFile *p = (MemFile *)pFile; - if( size>p->sz ){ - int rc; - if( size>p->szMax && (rc = memdbEnlarge(p, size))!=SQLITE_OK ){ - return rc; - } - memset(p->aData+p->sz, 0, size-p->sz); - } + if( NEVER(size>p->sz) ) return SQLITE_FULL; p->sz = size; return SQLITE_OK; } @@ -232,6 +230,7 @@ static int memdbLock(sqlite3_file *pFile, int eLock){ return SQLITE_OK; } +#if 0 /* Never used because memdbAccess() always returns false */ /* ** Check if another file-handle holds a RESERVED lock on an memdb-file. */ @@ -239,6 +238,7 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ *pResOut = 0; return SQLITE_OK; } +#endif /* ** File control method. For custom operations on an memdb-file. @@ -308,11 +308,14 @@ static int memdbOpen( } memset(p, 0, sizeof(*p)); p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; - if( pOutFlags ) *pOutFlags = flags | SQLITE_OPEN_MEMORY; + assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */ + *pOutFlags = flags | SQLITE_OPEN_MEMORY; p->base.pMethods = &memdb_io_methods; return SQLITE_OK; } +#if 0 /* Only used to delete rollback journals, master journals, and WAL + ** files, none of which exist in memdb. So this routine is never used */ /* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before @@ -321,10 +324,13 @@ static int memdbOpen( static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ return SQLITE_IOERR_DELETE; } +#endif /* ** Test for access permissions. Return true if the requested permission ** is available, or false otherwise. +** +** With memdb, no files ever exist on disk. So always return false. */ static int memdbAccess( sqlite3_vfs *pVfs, @@ -397,12 +403,14 @@ static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); } +#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ /* ** Return the current time as a Julian Day number in *pTimeOut. */ static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); } +#endif static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); @@ -528,15 +536,15 @@ int sqlite3_deserialize( goto end_deserialize; } p = memdbFromDbSchema(db, zSchema); - if( p==0 ){ - rc = SQLITE_ERROR; - }else{ - p->aData = pData; - p->sz = szDb; - p->szMax = szBuf; - p->mFlags = mFlags; - rc = SQLITE_OK; - } + /* The memdbFromDbSchema() call can only fail if zSchema is not + ** a valid schema name or if the schema is not a memdb schema. But + ** neither of those things can be true here, so failure is not possible */ + assert( p!=0 ); + p->aData = pData; + p->sz = szDb; + p->szMax = szBuf; + p->mFlags = mFlags; + rc = SQLITE_OK; end_deserialize: sqlite3_finalize(pStmt); sqlite3_mutex_leave(db->mutex); From 8784efaea94ea2ad37549db66e2c2b596223c26b Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 6 Mar 2018 20:54:27 +0000 Subject: [PATCH 12/14] Handle some boundary cases in memdb associated with OOM faults. FossilOrigin-Name: b58ca4cb0c921e81efad527c80b220be120263cfdb04528ae26ecf8b8f66f44a --- manifest | 14 ++++++------ manifest.uuid | 2 +- src/attach.c | 37 +++++++++++++++++--------------- src/memdb.c | 59 ++++++++++++++++++++++++++++----------------------- 4 files changed, 60 insertions(+), 52 deletions(-) diff --git a/manifest b/manifest index f599a85e45..962981e679 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplifications\sto\sthe\smemdb\sVFS. -D 2018-03-06T19:14:32.801 +C Handle\ssome\sboundary\scases\sin\smemdb\sassociated\swith\sOOM\sfaults. +D 2018-03-06T20:54:27.966 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -425,7 +425,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 6b42e36a5dcc2703a771f2411bd5e99524bd62c7ecde209bb88dfb04c72f046e -F src/attach.c e79ef463dc0a457281512c5a67c02d886a1a4502001bc9b7eb008e9b7c0f7bf3 +F src/attach.c 6a5619eaf0101b355922cb006e63458312d1067b80499e1df41cdd0ce37af99f F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -460,7 +460,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c ffdca40946f9cff49c6d0f452648233d1a5234bb1dfa456787ee82333164d126 +F src/memdb.c 3f14ea29aea3a43c39b83c392016a03790692007d751320ea8c19df03bb0b393 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a14fed69d0d4932fc6c71cf8acc5199cca4efbd10bca563a8e86038d6afd5c64 -R b9fff9a384a4ae44f14923e3716823bc +P 6c3f723a6856fa38ea3f11a36b56f46c5c1fcf17f4daf712e5e0b42562d5f4c6 +R 93b06b41fb0db58473fe3890ab6bb440 U drh -Z ed8ab2a467fe746aa3cc4991867879e0 +Z f2d702ac0939e1489f368e13dd72bca2 diff --git a/manifest.uuid b/manifest.uuid index 77b67bccf4..fb3d8af9ee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c3f723a6856fa38ea3f11a36b56f46c5c1fcf17f4daf712e5e0b42562d5f4c6 \ No newline at end of file +b58ca4cb0c921e81efad527c80b220be120263cfdb04528ae26ecf8b8f66f44a \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 9b07f89b79..09bd02be89 100644 --- a/src/attach.c +++ b/src/attach.c @@ -97,7 +97,7 @@ static void attachFunc( pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; pNew = &db->aDb[db->init.iDb]; - sqlite3BtreeClose(pNew->pBt); + if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); pNew->pBt = 0; pNew->pSchema = 0; rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); @@ -232,6 +232,7 @@ static void attachFunc( db->init.iDb = 0; rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); + assert( zErrDyn==0 || rc!=SQLITE_OK ); } #ifdef SQLITE_USER_AUTHENTICATION if( rc==SQLITE_OK ){ @@ -242,22 +243,24 @@ static void attachFunc( } } #endif - if( rc && !REOPEN_AS_MEMDB(db) ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + if( rc ){ + if( !REOPEN_AS_MEMDB(db) ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetAllSchemasOfConnection(db); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + } } goto attach_error; } diff --git a/src/memdb.c b/src/memdb.c index b2eefde955..88eaaba4ee 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -472,27 +472,31 @@ unsigned char *sqlite3_serialize( rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; sqlite3_free(zSql); if( rc ) return 0; - sqlite3_step(pStmt); - sz = sqlite3_column_int64(pStmt, 0)*szPage; - if( piSize ) *piSize = sz; - if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_ROW ){ pOut = 0; }else{ - pOut = sqlite3_malloc64( sz ); - if( pOut ){ - int nPage = sqlite3_column_int(pStmt, 0); - Pager *pPager = sqlite3BtreePager(pBt); - int pgno; - for(pgno=1; pgno<=nPage; pgno++){ - DbPage *pPage = 0; - unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); - rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); - if( rc==SQLITE_OK ){ - memcpy(pTo, sqlite3PagerGetData(pPage), szPage); - }else{ - memset(pTo, 0, szPage); + sz = sqlite3_column_int64(pStmt, 0)*szPage; + if( piSize ) *piSize = sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = 0; + }else{ + pOut = sqlite3_malloc64( sz ); + if( pOut ){ + int nPage = sqlite3_column_int(pStmt, 0); + Pager *pPager = sqlite3BtreePager(pBt); + int pgno; + for(pgno=1; pgno<=nPage; pgno++){ + DbPage *pPage = 0; + unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); + rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); + if( rc==SQLITE_OK ){ + memcpy(pTo, sqlite3PagerGetData(pPage), szPage); + }else{ + memset(pTo, 0, szPage); + } + sqlite3PagerUnref(pPage); } - sqlite3PagerUnref(pPage); } } } @@ -536,15 +540,16 @@ int sqlite3_deserialize( goto end_deserialize; } p = memdbFromDbSchema(db, zSchema); - /* The memdbFromDbSchema() call can only fail if zSchema is not - ** a valid schema name or if the schema is not a memdb schema. But - ** neither of those things can be true here, so failure is not possible */ - assert( p!=0 ); - p->aData = pData; - p->sz = szDb; - p->szMax = szBuf; - p->mFlags = mFlags; - rc = SQLITE_OK; + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + p->aData = pData; + p->sz = szDb; + p->szMax = szBuf; + p->mFlags = mFlags; + rc = SQLITE_OK; + } + end_deserialize: sqlite3_finalize(pStmt); sqlite3_mutex_leave(db->mutex); From 9c6396ecc788531b166dcbba833ab65a39abf501 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 6 Mar 2018 21:43:19 +0000 Subject: [PATCH 13/14] Improved documentation for sqlite3_serialize() and sqlite3_deserialize(). Change the name of the compile-time option to enable these interfaces from SQLITE_ENABLE_MEMDB to SQLITE_ENABLE_DESERIALIZE. FossilOrigin-Name: f07e97aed435b02e1473053c0257ec5c89bf0b3e46076b7a9382de432bbc2497 --- manifest | 28 ++++++++++++++-------------- manifest.uuid | 2 +- src/attach.c | 2 +- src/main.c | 2 +- src/memdb.c | 4 ++-- src/pager.c | 6 ++++++ src/sqlite.h.in | 36 ++++++++++++++++++++++++++++++++++-- src/sqliteInt.h | 2 +- src/tclsqlite.c | 4 ++-- src/test_config.c | 6 +++--- test/memdb1.test | 2 +- 11 files changed, 66 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index 962981e679..18c42ee4e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Handle\ssome\sboundary\scases\sin\smemdb\sassociated\swith\sOOM\sfaults. -D 2018-03-06T20:54:27.966 +C Improved\sdocumentation\sfor\ssqlite3_serialize()\sand\ssqlite3_deserialize().\nChange\sthe\sname\sof\sthe\scompile-time\soption\sto\senable\sthese\sinterfaces\nfrom\sSQLITE_ENABLE_MEMDB\sto\sSQLITE_ENABLE_DESERIALIZE. +D 2018-03-06T21:43:19.244 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -425,7 +425,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 6b42e36a5dcc2703a771f2411bd5e99524bd62c7ecde209bb88dfb04c72f046e -F src/attach.c 6a5619eaf0101b355922cb006e63458312d1067b80499e1df41cdd0ce37af99f +F src/attach.c f6f212c43dddba79dfcb723fb9470785f3ff55bde8953cd9d2546f3022070a41 F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 @@ -453,14 +453,14 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 14686083cedc198540b15a79586cdd4be2acf6d5fa97627e355f817ab07e9fee F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302 -F src/main.c d45d07a1c707f88cf734ec7699d9c393247f18682d748ab53065fb669231f66a +F src/main.c c1e97e4c6fffff1fb1a6f1c48807386819af78657b4ae4acfd6d6d17353b8277 F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c 3f14ea29aea3a43c39b83c392016a03790692007d751320ea8c19df03bb0b393 +F src/memdb.c f5d49ef349a07df3b855885c4a0f3d8d688ca9a9c82093e9ed6a399a4826abea F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -476,7 +476,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 928586cbde31890538854f1657463392d63b2d7794f577774573ae53ec283d7b F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 0dc92667c803ed2e9566c35521bed2c53717197b011bc7b64d17cd552a241a7b +F src/pager.c aa764a01a5548e633ea083521f48c2b128245fae1a8157a16a3490b9b9718f55 F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a F src/parse.y 3be4b2b5e33ef7dab3128b765898ee786fc6cd698a7f053f756a68f2f238f0aa F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 @@ -491,14 +491,14 @@ F src/resolve.c 66c73fcb7719b8ff0e841b58338f13604ff3e2b50a723f9b8f383595735262f6 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c f02352ac5cbb6fad3804add825743b924cfb6c742ba2e8666d726828a9985d73 F src/shell.c.in 8c6ea9b4da9450c26551bbe7de24170e5c6c6e3af4dedaa663e3f5ef05659a96 -F src/sqlite.h.in 82eb2b02de6dda3ca9797a5a5418c8409e2aaf5b4f20530a9036722faa0cc43c +F src/sqlite.h.in 8125abd15ff083591e53e1bc874319fbfaf239b1c57563c9685bd42723f8926a F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h 574a0dd6978197cc1f9b8d571744c9a30e256d29a3092050bd8a95e37c7229b9 +F src/sqliteInt.h 2ef60a6d9a50e6eef224e9eae71b29a9fb91c301e882d9fbbb77afd50b6cf815 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c d05dde2bb9534ee39a5095c4c4a43625997e0f3ab6889b55e76393b05b6895b1 +F src/tclsqlite.c 3c3e085e02edf4c416792050d288944fd0fad3f7b283a81fa45241a633d78c80 F src/test1.c 1ab7cbbb6693e08364c1a9241e2aee17f8c4925e4cc52396be77ae6845a05828 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b @@ -514,7 +514,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c 09bd69f7e59bad08b67dd7bd8e7de6d992f1a668466b4500c870139fe1792126 +F src/test_config.c 097c6189803886a1fb26ec37d8bc62b90512cb53ab79a1fb6d35196c1ec42ded F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -1067,7 +1067,7 @@ F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test 526252d466ecc3701550000651e1405d08ccefe0bf23e2dc86ada90e81a8eacc +F test/memdb1.test fbe47f36c12725ebdd2760f846371e6eb09f403bd7236fbdddb21aa6e3c652b4 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6c3f723a6856fa38ea3f11a36b56f46c5c1fcf17f4daf712e5e0b42562d5f4c6 -R 93b06b41fb0db58473fe3890ab6bb440 +P b58ca4cb0c921e81efad527c80b220be120263cfdb04528ae26ecf8b8f66f44a +R 8d936538e4c856e0f588396347b85dcc U drh -Z f2d702ac0939e1489f368e13dd72bca2 +Z c61ba7a8db0957766315d0dc5cf0b993 diff --git a/manifest.uuid b/manifest.uuid index fb3d8af9ee..6fe0b07e1f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b58ca4cb0c921e81efad527c80b220be120263cfdb04528ae26ecf8b8f66f44a \ No newline at end of file +f07e97aed435b02e1473053c0257ec5c89bf0b3e46076b7a9382de432bbc2497 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 09bd02be89..f85952f7c6 100644 --- a/src/attach.c +++ b/src/attach.c @@ -84,7 +84,7 @@ static void attachFunc( if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; -#ifdef SQLITE_ENABLE_MEMDB +#ifdef SQLITE_ENABLE_DESERIALIZE # define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) #else # define REOPEN_AS_MEMDB(db) (0) diff --git a/src/main.c b/src/main.c index 2fef116868..af93a011e3 100644 --- a/src/main.c +++ b/src/main.c @@ -239,7 +239,7 @@ int sqlite3_initialize(void){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } -#ifdef SQLITE_ENABLE_MEMDB +#ifdef SQLITE_ENABLE_DESERIALIZE if( rc==SQLITE_OK ){ rc = sqlite3MemdbInit(); } diff --git a/src/memdb.c b/src/memdb.c index 88eaaba4ee..646f788feb 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -16,7 +16,7 @@ ** This file also implements interface sqlite3_serialize() and ** sqlite3_deserialize(). */ -#ifdef SQLITE_ENABLE_MEMDB +#ifdef SQLITE_ENABLE_DESERIALIZE #include "sqliteInt.h" /* @@ -568,4 +568,4 @@ int sqlite3MemdbInit(void){ memdb_vfs.szOsFile = sz; return sqlite3_vfs_register(&memdb_vfs, 0); } -#endif /* SQLITE_ENABLE_MEMDB */ +#endif /* SQLITE_ENABLE_DESERIALIZE */ diff --git a/src/pager.c b/src/pager.c index 175c94ddd8..f4ac88c206 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4723,7 +4723,11 @@ int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ +#ifdef SQLITE_ENABLE_DESERIALIZE int memJM = 0; /* Memory journal mode */ +#else +# define memJM 0 +#endif int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ @@ -4851,7 +4855,9 @@ int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); +#ifdef SQLITE_ENABLE_DESERIALIZE memJM = (fout&SQLITE_OPEN_MEMORY)!=0; +#endif readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 75a96d50d6..4e7939ebda 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8762,6 +8762,9 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. */ unsigned char *sqlite3_serialize( sqlite3 *db, /* The database connection */ @@ -8773,6 +8776,17 @@ unsigned char *sqlite3_serialize( /* ** CAPI3REF: Flags for sqlite3_serialize ** EXPERIMENTAL +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. */ #define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ @@ -8802,6 +8816,9 @@ unsigned char *sqlite3_serialize( ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. */ int sqlite3_deserialize( sqlite3 *db, /* The database connection */ @@ -8816,8 +8833,23 @@ int sqlite3_deserialize( ** CAPI3REF: Flags for sqlite3_deserialize() ** EXPERIMENTAL ** -** The following are allowed values for the 6th argument (the "flags" or "F" -** argument) of the [sqlite3_deserialize()] interface. +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is resposible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database usign calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. */ #define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ #define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 341cfe97a6..3f34f48e15 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4024,7 +4024,7 @@ int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); const char *sqlite3ErrName(int); #endif -#ifdef SQLITE_ENABLE_MEMDB +#ifdef SQLITE_ENABLE_DESERIALIZE int sqlite3MemdbInit(void); #endif diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 878cdd961d..285fbbda2e 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2420,7 +2420,7 @@ static int SQLITE_TCLAPI DbObjCmd( ** Reopen DATABASE (default "main") using the content in $VALUE */ case DB_DESERIALIZE: { -#ifndef SQLITE_ENABLE_MEMDB +#ifndef SQLITE_ENABLE_DESERIALIZE Tcl_AppendResult(interp, "MEMDB not available in this build", (char*)0); rc = TCL_ERROR; @@ -2942,7 +2942,7 @@ static int SQLITE_TCLAPI DbObjCmd( ** Return a serialization of a database. */ case DB_SERIALIZE: { -#ifndef SQLITE_ENABLE_MEMDB +#ifndef SQLITE_ENABLE_DESERIALIZE Tcl_AppendResult(interp, "MEMDB not available in this build", (char*)0); rc = TCL_ERROR; diff --git a/src/test_config.c b/src/test_config.c index de693850d3..aa0626ab2d 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -148,10 +148,10 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "hiddencolumns", "0", TCL_GLOBAL_ONLY); #endif -#ifdef SQLITE_ENABLE_MEMDB - Tcl_SetVar2(interp, "sqlite_options", "memdb", "1", TCL_GLOBAL_ONLY); +#ifdef SQLITE_ENABLE_DESERIALIZE + Tcl_SetVar2(interp, "sqlite_options", "deserialize", "1", TCL_GLOBAL_ONLY); #else - Tcl_SetVar2(interp, "sqlite_options", "memdb", "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_MEMSYS3 diff --git a/test/memdb1.test b/test/memdb1.test index 48f9fca5ec..b52517fcf3 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -17,7 +17,7 @@ source $testdir/tester.tcl set testprefix memdb1 do_not_use_codec -ifcapable !memdb { +ifcapable !deserialize { finish_test return } From 4811a710af213de51e1ca93d293878d87fe69ef6 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 7 Mar 2018 01:37:05 +0000 Subject: [PATCH 14/14] Mark an unreachable branch using NEVER(). FossilOrigin-Name: fadbc5e23f93bedd705bdc83cd3781b3821a231034bae5b942c94da77227721c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/memdb.c | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 18c42ee4e2..815ce0cb70 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sdocumentation\sfor\ssqlite3_serialize()\sand\ssqlite3_deserialize().\nChange\sthe\sname\sof\sthe\scompile-time\soption\sto\senable\sthese\sinterfaces\nfrom\sSQLITE_ENABLE_MEMDB\sto\sSQLITE_ENABLE_DESERIALIZE. -D 2018-03-06T21:43:19.244 +C Mark\san\sunreachable\sbranch\susing\sNEVER(). +D 2018-03-07T01:37:05.387 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 @@ -460,7 +460,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 -F src/memdb.c f5d49ef349a07df3b855885c4a0f3d8d688ca9a9c82093e9ed6a399a4826abea +F src/memdb.c 00ece105cf2cc1fcf0faf8151a1bcde50d19ae99437ee646b0cad457e469a896 F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81 F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53 @@ -1710,7 +1710,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b58ca4cb0c921e81efad527c80b220be120263cfdb04528ae26ecf8b8f66f44a -R 8d936538e4c856e0f588396347b85dcc +P f07e97aed435b02e1473053c0257ec5c89bf0b3e46076b7a9382de432bbc2497 +R 1be29732572fe3143eab743f97b3559e U drh -Z c61ba7a8db0957766315d0dc5cf0b993 +Z fc974f7768a62ed16a0f51a5a0679333 diff --git a/manifest.uuid b/manifest.uuid index 6fe0b07e1f..0219ff2513 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f07e97aed435b02e1473053c0257ec5c89bf0b3e46076b7a9382de432bbc2497 \ No newline at end of file +fadbc5e23f93bedd705bdc83cd3781b3821a231034bae5b942c94da77227721c \ No newline at end of file diff --git a/src/memdb.c b/src/memdb.c index 646f788feb..320c70865f 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -564,7 +564,10 @@ int sqlite3MemdbInit(void){ sqlite3_vfs *pLower = sqlite3_vfs_find(0); int sz = pLower->szOsFile; memdb_vfs.pAppData = pLower; - if( sz