diff options
author | drh <drh@noemail.net> | 2018-01-03 16:49:52 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2018-01-03 16:49:52 +0000 |
commit | cb7d541d3ae005e24bb0d36bb138d84a3ca3d415 (patch) | |
tree | c594ecd7b9f257a531db3fc9b8712527814d68dc | |
parent | 4dcac40e3d4cf02513c84c95ccd4198ef35f2320 (diff) | |
download | sqlite-cb7d541d3ae005e24bb0d36bb138d84a3ca3d415.tar.gz sqlite-cb7d541d3ae005e24bb0d36bb138d84a3ca3d415.zip |
Replace the sqlite3_memdb_ptr() interface with the more general
sqlite3_serialize() interface.
FossilOrigin-Name: 8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077
-rw-r--r-- | manifest | 20 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/memdb.c | 81 | ||||
-rw-r--r-- | src/sqlite.h.in | 111 | ||||
-rw-r--r-- | src/tclsqlite.c | 108 | ||||
-rw-r--r-- | test/memdb1.test | 7 | ||||
-rw-r--r-- | tool/mkopts.tcl | 4 |
7 files changed, 250 insertions, 83 deletions
@@ -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 2905c1c5a..a6d77e2b7 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 215bfbb24..0a81978cc 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( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); return SQLITE_IOERR_SHORT_READ; } memcpy(zBuf, p->aData+iOfst, iAmt); @@ -450,20 +451,6 @@ static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ } /* -** 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( @@ -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 143448553..6b6a5655b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8759,22 +8759,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 d02d94baf..2c6e1bbe2 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 */ @@ -2412,6 +2414,16 @@ static int SQLITE_TCLAPI DbObjCmd( } /* + ** $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 ** ** Turn the extension loading feature on or off. It if off by @@ -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 ); @@ -2934,6 +2937,39 @@ static int SQLITE_TCLAPI DbObjCmd( } /* + ** $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) ** ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or diff --git a/test/memdb1.test b/test/memdb1.test index 13ef57ace..36184e2e4 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 e3ddcb9ee..88f645bbe 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 |