]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Replace sqlite3_memdb_config() with sqlite3_deserialize(). Remove the
authordrh <drh@noemail.net>
Wed, 3 Jan 2018 19:03:31 +0000 (19:03 +0000)
committerdrh <drh@noemail.net>
Wed, 3 Jan 2018 19:03:31 +0000 (19:03 +0000)
"db memdb" command from the TCL interface, replacing it with "db serialize"
and "db deserialize".

FossilOrigin-Name: 2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac

manifest
manifest.uuid
src/attach.c
src/memdb.c
src/sqlite.h.in
src/sqliteInt.h
src/tclsqlite.c
test/memdb1.test
test/tclsqlite.test

index 892a7572e4593b22bc2a61a438551beeec967ea5..cde71db315e54753401ebe5e1b5358083d0fec51 100644 (file)
--- 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
index a6d77e2b7f873cbe10ce399d0b8cea58a284d76e..08b82513bb5b156944002a0944921519a09d80e5 100644 (file)
@@ -1 +1 @@
-8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077
\ No newline at end of file
+2f6e9df9f0c5a9e5b1acb99cfa9486850cc1822d35b0989e779a7a10f3b1f1ac
\ No newline at end of file
index fa38e84159d4a4144146bb9a9d08f15e06b8ece8..151b52e7a4b900f82547ccc3291ca8f6c1cc6205 100644 (file)
@@ -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; i<db->nDb; 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; i<db->nDb; 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);
index 0a81978cceb6a1b2009f65f22b9d48210f09c0c4..5a1f12dcbbfa143e59b5154b7fb320dfcb889c99 100644 (file)
 **
 ** 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.
index 6b6a5655b3290ee9ec0a22248b0f432ce9ae74b6..233a2cf60e485f7b35f2c602a8272c812d480dfe 100644 (file)
@@ -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 
index 002fb4e916e505b0652c3acc7b1a8ebff55714b4..35074ee81a994f03c208a4f9bdc600dab3744ce6 100644 (file)
@@ -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 */
index 2c6e1bbe27d594e0ba8453867ff24df35d81aa1d..c9b4ff61079c0f5665a38278aea82a4491ae10b2 100644 (file)
@@ -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));
index 36184e2e4e9053653e8f2d677ec53132436fb9f1..c37cac26649ee6ed3330882759d6d80e9856ffde 100644 (file)
@@ -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}
index ca53710ec217809a00b56b60b8561614c71d9a84..fb4be3dfcb252b3c6a20df3a933cdb2d7c99f2c3 100644 (file)
@@ -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