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

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

Overview
Comment:Replace the sqlite3_memdb_ptr() interface with the more general sqlite3_serialize() interface.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | memdb
Files: files | file ages | folders
SHA3-256: 8cf2ed4eff6d2e0958656e23384b05ead2128b678b0b69a591878af4190cd077
User & Date: drh 2018-01-03 16:49:52
Context
2018-01-03
19:03
Replace sqlite3_memdb_config() with sqlite3_deserialize(). Remove the "db memdb" command from the TCL interface, replacing it with "db serialize" and "db deserialize". check-in: 2f6e9df9 user: drh tags: memdb
16:49
Replace the sqlite3_memdb_ptr() interface with the more general sqlite3_serialize() interface. check-in: 8cf2ed4e user: drh tags: memdb
13:20
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. check-in: 47398ae7 user: drh tags: memdb
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/memdb.c.

153
154
155
156
157
158
159

160
161
162
163
164
165
166
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
489
490
491
492
493
494
495


































































496
497
498
499
500
501
502
503
504
505
506
  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;
}

/*
................................................................................
  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,
................................................................................
    rc = SQLITE_OK;
  }
  if( rc!=SQLITE_OK && (mFlags & SQLITE_MEMDB_FREEONCLOSE)!=0 ){
    sqlite3_free(aData);
  }
  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 */







>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
446
447
448
449
450
451
452














453
454
455
456
457
458
459
...
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  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);
  return SQLITE_OK;
}

/*
................................................................................
  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;
}















/*
** Reconfigure a memdb database.
*/
int sqlite3_memdb_config(
  sqlite3 *db,
  const char *zSchema,
  void *aData,
................................................................................
    rc = SQLITE_OK;
  }
  if( rc!=SQLITE_OK && (mFlags & SQLITE_MEMDB_FREEONCLOSE)!=0 ){
    sqlite3_free(aData);
  }
  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.
*/
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 */

Changes to src/sqlite.h.in.

8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799





























































































8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
** transaction open on the database, or if the database is not a wal mode
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
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.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif /* SQLITE3_H */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













8754
8755
8756
8757
8758
8759
8760
















8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
** transaction open on the database, or if the database is not a wal mode
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
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
**
** 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
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif /* SQLITE3_H */

Changes to src/tclsqlite.c.

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868

1869
1870
1871
1872
1873
1874
1875


1876
1877
1878
1879
1880
1881
1882
1883
....
2406
2407
2408
2409
2410
2411
2412










2413
2414
2415
2416
2417
2418
2419
....
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
....
2928
2929
2930
2931
2932
2933
2934

































2935
2936
2937
2938
2939
2940
2941
  int objc,
  Tcl_Obj *const*objv
){
  SqliteDb *pDb = (SqliteDb*)cd;
  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
  };
  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
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
................................................................................
      sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
      Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
                       (char*)0);
      rc = TCL_ERROR;
    }
    break;
  }











  /*
  **    $db enable_load_extension BOOLEAN
  **
  ** Turn the extension loading feature on or off.  It if off by
  ** default.
  */
................................................................................
  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{
................................................................................
      Tcl_AppendResult(interp, "restore failed: ",
           sqlite3_errmsg(pDb->db), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_close(pSrc);
    break;
  }


































  /*
  **     $db status (step|sort|autoindex|vmstep)
  **
  ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
  ** SQLITE_STMTSTATUS_SORT for the most recent eval.
  */







|
|
|
|
|
|
|
|
|
|
|
|
>
|


|
|
<
|
|
>
|
|
|
|
|
<
|
>
>
|







 







>
>
>
>
>
>
>
>
>
>







 







<

<
<
<
<
<
<
<
<
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
....
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
....
2687
2688
2689
2690
2691
2692
2693

2694








2695
2696
2697
2698
2699
2700
2701
2702
....
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
  int objc,
  Tcl_Obj *const*objv
){
  SqliteDb *pDb = (SqliteDb*)cd;
  int choice;
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "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_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 */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
................................................................................
      sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
      Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
                       (char*)0);
      rc = TCL_ERROR;
    }
    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
  **
  ** Turn the extension loading feature on or off.  It if off by
  ** default.
  */
................................................................................
  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{
................................................................................
      Tcl_AppendResult(interp, "restore failed: ",
           sqlite3_errmsg(pDb->db), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_close(pSrc);
    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)
  **
  ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or
  ** SQLITE_STMTSTATUS_SORT for the most recent eval.
  */

Changes to test/memdb1.test.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44



45
46
47
48
49
50
51
52
53
54
55
56
}

# 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 -memdb $db1
do_execsql_test 110 {
  SELECT * FROM t1;
} {1 2}


finish_test







<
<










|


>
>
>












23
24
25
26
27
28
29


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
}

# 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.
#


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 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.
#
db close
sqlite3 db -memdb $db1
do_execsql_test 110 {
  SELECT * FROM t1;
} {1 2}


finish_test

Changes to tool/mkopts.tcl.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

set prefix {}
while {![eof stdin]} {
  set line [gets 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
    lappend namelist [string tolower $name]
    if {$px!=""} {set prefix $p2}
  }
}

puts "  static const char *${prefix}_strs\[\] = \173"
set col 0
proc put_item x {
  global col
  if {$col==0} {puts -nonewline "   "}
  if {$col<2} {
    puts -nonewline [format " %-21s" $x]
    incr col
  } else {
    puts $x
    set col 0
  }
}
proc finalize {} {







|











|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

set prefix {}
while {![eof stdin]} {
  set line [gets stdin]
  if {$line==""} continue
  regsub -all "\[ \t\n,\]+" [string trim $line] { } line
  foreach token [split $line { }] {
    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}
  }
}

puts "  static const char *${prefix}_strs\[\] = \173"
set col 0
proc put_item x {
  global col
  if {$col==0} {puts -nonewline "   "}
  if {$col<2} {
    puts -nonewline [format " %-25s" $x]
    incr col
  } else {
    puts $x
    set col 0
  }
}
proc finalize {} {