1/*
2** Read an SQLite database file and analyze its space utilization.  Generate
3** text on standard output.
4*/
5#define TCLSH_INIT_PROC sqlite3_checker_init_proc
6#define SQLITE_ENABLE_DBPAGE_VTAB 1
7#undef SQLITE_THREADSAFE
8#define SQLITE_THREADSAFE 0
9#undef SQLITE_ENABLE_COLUMN_METADATA
10#define SQLITE_OMIT_DECLTYPE 1
11#define SQLITE_OMIT_DEPRECATED 1
12#define SQLITE_OMIT_PROGRESS_CALLBACK 1
13#define SQLITE_OMIT_SHARED_CACHE 1
14#define SQLITE_DEFAULT_MEMSTATUS 0
15#define SQLITE_MAX_EXPR_DEPTH 0
16INCLUDE sqlite3.c
17INCLUDE $ROOT/src/tclsqlite.c
18INCLUDE $ROOT/ext/misc/btreeinfo.c
19INCLUDE $ROOT/ext/repair/checkindex.c
20INCLUDE $ROOT/ext/repair/checkfreelist.c
21
22/*
23** Decode a pointer to an sqlite3 object.
24*/
25int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
26  struct SqliteDb *p;
27  Tcl_CmdInfo cmdInfo;
28  if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
29    p = (struct SqliteDb*)cmdInfo.objClientData;
30    *ppDb = p->db;
31    return TCL_OK;
32  }else{
33    *ppDb = 0;
34    return TCL_ERROR;
35  }
36  return TCL_OK;
37}
38
39/*
40**   sqlite3_imposter db main rootpage {CREATE TABLE...}  ;# setup an imposter
41**   sqlite3_imposter db main                             ;# rm all imposters
42*/
43static int sqlite3_imposter(
44  void *clientData,
45  Tcl_Interp *interp,
46  int objc,
47  Tcl_Obj *CONST objv[]
48){
49  sqlite3 *db;
50  const char *zSchema;
51  int iRoot;
52  const char *zSql;
53
54  if( objc!=3 && objc!=5 ){
55    Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
56    return TCL_ERROR;
57  }
58  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
59  zSchema = Tcl_GetString(objv[2]);
60  if( objc==3 ){
61    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
62  }else{
63    if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
64    zSql = Tcl_GetString(objv[4]);
65    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
66    sqlite3_exec(db, zSql, 0, 0, 0);
67    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
68  }
69  return TCL_OK;
70}
71
72#include <stdio.h>
73
74const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
75  Tcl_CreateObjCommand(interp, "sqlite3_imposter",
76                       (Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
77  sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
78  sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
79  sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
80  return
81BEGIN_STRING
82INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
83END_STRING
84;
85}
86