gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/startup.c (about)

     1  /*
     2  ** 2021-01-01
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  ** 
    13  ** This file implements a program used to measure the start-up performance
    14  ** of SQLite.
    15  **
    16  ** To use:
    17  **
    18  **     ./startup init
    19  **     valgrind --tool=cachegrind ./startup run
    20  **
    21  **
    22  ** The "./startup init" command creates the test database file named
    23  ** "startup.db".  The performance test is run by the "./startup run"
    24  ** command.  That command does nothing but open the database file and
    25  ** parse the entire schema.
    26  */
    27  #include <stdio.h>
    28  #include <unistd.h>
    29  #include <string.h>
    30  #include <stdlib.h>
    31  #include <ctype.h>
    32  #include "sqlite3.h"
    33  
    34  static const char zHelp[] =
    35    "Usage: %s COMMAND\n"
    36    "Commands:\n"
    37    "  init                Initialized the startup.db database file\n"
    38    "  run                 Run the startup performance test\n"
    39    "Options:\n"
    40    "  --dbname NAME       Set the name of the test database file\n"
    41    "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
    42    "  --stats             Show statistics at the end\n"
    43  /* TBD
    44    "  --journal M         Set the journal_mode to M\n"
    45    "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
    46    "  --mmap SZ           MMAP the first SZ bytes of the database file\n"
    47    "  --multithread       Set multithreaded mode\n"
    48    "  --nomemstat         Disable memory statistics\n"
    49    "  --pagesize N        Set the page size to N\n"
    50    "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
    51    "  --serialized        Set serialized threading mode\n"
    52    "  --singlethread      Set single-threaded mode - disables all mutexing\n"
    53    "  --utf16be           Set text encoding to UTF-16BE\n"
    54    "  --utf16le           Set text encoding to UTF-16LE\n"
    55    "  --utf8              Set text encoding to UTF-8\n"
    56  */
    57  ;
    58  
    59  static void usage(const char *argv0){
    60    printf(zHelp, argv0);
    61    exit(1);
    62  }
    63  
    64  /*
    65  ** The test schema is derived from the Fossil repository for SQLite itself.
    66  ** The schema covers the repository, the local checkout database, and
    67  ** the global configuration database.
    68  */
    69  static const char zTestSchema[] = 
    70    "CREATE TABLE repo_blob(\n"
    71    "  rid INTEGER PRIMARY KEY,\n"
    72    "  rcvid INTEGER,\n"
    73    "  size INTEGER,\n"
    74    "  uuid TEXT UNIQUE NOT NULL,\n"
    75    "  content BLOB,\n"
    76    "  CHECK( length(uuid)>=40 AND rid>0 )\n"
    77    ");\n"
    78    "CREATE TABLE repo_delta(\n"
    79    "  rid INTEGER PRIMARY KEY,\n"
    80    "  srcid INTEGER NOT NULL REFERENCES blob\n"
    81    ");\n"
    82    "CREATE TABLE repo_rcvfrom(\n"
    83    "  rcvid INTEGER PRIMARY KEY,\n"
    84    "  uid INTEGER REFERENCES user,\n"
    85    "  mtime DATETIME,\n"
    86    "  nonce TEXT UNIQUE,\n"
    87    "  ipaddr TEXT\n"
    88    ");\n"
    89    "CREATE TABLE repo_private(rid INTEGER PRIMARY KEY);\n"
    90    "CREATE TABLE repo_accesslog(\n"
    91    "  uname TEXT,\n"
    92    "  ipaddr TEXT,\n"
    93    "  success BOOLEAN,\n"
    94    "  mtime TIMESTAMP);\n"
    95    "CREATE TABLE repo_user(\n"
    96    "  uid INTEGER PRIMARY KEY,\n"
    97    "  login TEXT UNIQUE,\n"
    98    "  pw TEXT,\n"
    99    "  cap TEXT,\n"
   100    "  cookie TEXT,\n"
   101    "  ipaddr TEXT,\n"
   102    "  cexpire DATETIME,\n"
   103    "  info TEXT,\n"
   104    "  mtime DATE,\n"
   105    "  photo BLOB\n"
   106    ");\n"
   107    "CREATE TABLE repo_reportfmt(\n"
   108    "   rn INTEGER PRIMARY KEY,\n"
   109    "   owner TEXT,\n"
   110    "   title TEXT UNIQUE,\n"
   111    "   mtime INTEGER,\n"
   112    "   cols TEXT,\n"
   113    "   sqlcode TEXT\n"
   114    ");\n"
   115    "CREATE TABLE repo_sqlite_stat2(tbl,idx,sampleno,sample);\n"
   116    "CREATE TABLE repo_sqlite_stat1(tbl,idx,stat);\n"
   117    "CREATE TABLE repo_sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);\n"
   118    "CREATE TABLE repo_config(\n"
   119    "  name TEXT PRIMARY KEY NOT NULL,\n"
   120    "  value CLOB, mtime INTEGER,\n"
   121    "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
   122    ") WITHOUT ROWID;\n"
   123    "CREATE TABLE repo_shun(uuid PRIMARY KEY,\n"
   124    "  mtime INTEGER,\n"
   125    "  scom TEXT) WITHOUT ROWID;\n"
   126    "CREATE TABLE repo_concealed(\n"
   127    "  hash TEXT PRIMARY KEY,\n"
   128    "  content TEXT\n"
   129    ", mtime INTEGER) WITHOUT ROWID;\n"
   130    "CREATE TABLE repo_admin_log(\n"
   131    " id INTEGER PRIMARY KEY,\n"
   132    " time INTEGER, -- Seconds since 1970\n"
   133    " page TEXT,    -- path of page\n"
   134    " who TEXT,     -- User who made the change\n"
   135    "  what TEXT     -- What changed\n"
   136    ");\n"
   137    "CREATE TABLE repo_unversioned(\n"
   138    "  name TEXT PRIMARY KEY,\n"
   139    "  rcvid INTEGER,\n"
   140    "  mtime DATETIME,\n"
   141    "  hash TEXT,\n"
   142    "  sz INTEGER,\n"
   143    "  encoding INT,\n"
   144    "  content BLOB\n"
   145    ") WITHOUT ROWID;\n"
   146    "CREATE TABLE repo_subscriber(\n"
   147    "  subscriberId INTEGER PRIMARY KEY,\n"
   148    "  subscriberCode BLOB DEFAULT (randomblob(32)) UNIQUE,\n"
   149    "  semail TEXT UNIQUE COLLATE nocase,\n"
   150    "  suname TEXT,\n"
   151    "  sverified BOOLEAN DEFAULT true,\n"
   152    "  sdonotcall BOOLEAN,\n"
   153    "  sdigest BOOLEAN,\n"
   154    "  ssub TEXT,\n"
   155    "  sctime INTDATE,\n"
   156    "  mtime INTDATE,\n"
   157    "  smip TEXT\n"
   158    ");\n"
   159    "CREATE TABLE repo_pending_alert(\n"
   160    "  eventid TEXT PRIMARY KEY,\n"
   161    "  sentSep BOOLEAN DEFAULT false,\n"
   162    "  sentDigest BOOLEAN DEFAULT false\n"
   163    ", sentMod BOOLEAN DEFAULT false) WITHOUT ROWID;\n"
   164    "CREATE INDEX repo_delta_i1 ON repo_delta(srcid);\n"
   165    "CREATE INDEX repo_blob_rcvid ON repo_blob(rcvid);\n"
   166    "CREATE INDEX repo_subscriberUname\n"
   167    "  ON repo_subscriber(suname) WHERE suname IS NOT NULL;\n"
   168    "CREATE VIEW repo_artifact(rid,rcvid,size,atype,srcid,hash,content) AS\n"
   169    "     SELECT blob.rid,rcvid,size,1,srcid,uuid,content\n"
   170    "       FROM repo_blob LEFT JOIN repo_delta ON (blob.rid=delta.rid);\n"
   171    "CREATE TABLE repo_filename(\n"
   172    "  fnid INTEGER PRIMARY KEY,\n"
   173    "  name TEXT UNIQUE\n"
   174    ");\n"
   175    "CREATE TABLE repo_mlink(\n"
   176    "  mid INTEGER,\n"
   177    "  fid INTEGER,\n"
   178    "  pmid INTEGER,\n"
   179    "  pid INTEGER,\n"
   180    "  fnid INTEGER REFERENCES filename,\n"
   181    "  pfnid INTEGER,\n"
   182    "  mperm INTEGER,\n"
   183    "  isaux BOOLEAN DEFAULT 0\n"
   184    ");\n"
   185    "CREATE INDEX repo_mlink_i1 ON repo_mlink(mid);\n"
   186    "CREATE INDEX repo_mlink_i2 ON repo_mlink(fnid);\n"
   187    "CREATE INDEX repo_mlink_i3 ON repo_mlink(fid);\n"
   188    "CREATE INDEX repo_mlink_i4 ON repo_mlink(pid);\n"
   189    "CREATE TABLE repo_plink(\n"
   190    "  pid INTEGER REFERENCES blob,\n"
   191    "  cid INTEGER REFERENCES blob,\n"
   192    "  isprim BOOLEAN,\n"
   193    "  mtime DATETIME,\n"
   194    "  baseid INTEGER REFERENCES blob,\n"
   195    "  UNIQUE(pid, cid)\n"
   196    ");\n"
   197    "CREATE INDEX repo_plink_i2 ON repo_plink(cid,pid);\n"
   198    "CREATE TABLE repo_leaf(rid INTEGER PRIMARY KEY);\n"
   199    "CREATE TABLE repo_event(\n"
   200    "  type TEXT,\n"
   201    "  mtime DATETIME,\n"
   202    "  objid INTEGER PRIMARY KEY,\n"
   203    "  tagid INTEGER,\n"
   204    "  uid INTEGER REFERENCES user,\n"
   205    "  bgcolor TEXT,\n"
   206    "  euser TEXT,\n"
   207    "  user TEXT,\n"
   208    "  ecomment TEXT,\n"
   209    "  comment TEXT,\n"
   210    "  brief TEXT,\n"
   211    "  omtime DATETIME\n"
   212    ");\n"
   213    "CREATE INDEX repo_event_i1 ON repo_event(mtime);\n"
   214    "CREATE TABLE repo_phantom(\n"
   215    "  rid INTEGER PRIMARY KEY\n"
   216    ");\n"
   217    "CREATE TABLE repo_orphan(\n"
   218    "  rid INTEGER PRIMARY KEY,\n"
   219    "  baseline INTEGER\n"
   220    ");\n"
   221    "CREATE INDEX repo_orphan_baseline ON repo_orphan(baseline);\n"
   222    "CREATE TABLE repo_unclustered(\n"
   223    "  rid INTEGER PRIMARY KEY\n"
   224    ");\n"
   225    "CREATE TABLE repo_unsent(\n"
   226    "  rid INTEGER PRIMARY KEY\n"
   227    ");\n"
   228    "CREATE TABLE repo_tag(\n"
   229    "  tagid INTEGER PRIMARY KEY,\n"
   230    "  tagname TEXT UNIQUE\n"
   231    ");\n"
   232    "CREATE TABLE repo_tagxref(\n"
   233    "  tagid INTEGER REFERENCES tag,\n"
   234    "  tagtype INTEGER,\n"
   235    "  srcid INTEGER REFERENCES blob,\n"
   236    "  origid INTEGER REFERENCES blob,\n"
   237    "  value TEXT,\n"
   238    "  mtime TIMESTAMP,\n"
   239    "  rid INTEGER REFERENCE blob,\n"
   240    "  UNIQUE(rid, tagid)\n"
   241    ");\n"
   242    "CREATE INDEX repo_tagxref_i1 ON repo_tagxref(tagid, mtime);\n"
   243    "CREATE TABLE repo_backlink(\n"
   244    "  target TEXT,\n"
   245    "  srctype INT,\n"
   246    "  srcid INT,\n"
   247    "  mtime TIMESTAMP,\n"
   248    "  UNIQUE(target, srctype, srcid)\n"
   249    ");\n"
   250    "CREATE INDEX repo_backlink_src ON repo_backlink(srcid, srctype);\n"
   251    "CREATE TABLE repo_attachment(\n"
   252    "  attachid INTEGER PRIMARY KEY,\n"
   253    "  isLatest BOOLEAN DEFAULT 0,\n"
   254    "  mtime TIMESTAMP,\n"
   255    "  src TEXT,\n"
   256    "  target TEXT,\n"
   257    "  filename TEXT,\n"
   258    "  comment TEXT,\n"
   259    "  user TEXT\n"
   260    ");\n"
   261    "CREATE INDEX repo_attachment_idx1\n"
   262    " ON repo_attachment(target, filename, mtime);\n"
   263    "CREATE INDEX repo_attachment_idx2 ON repo_attachment(src);\n"
   264    "CREATE TABLE repo_cherrypick(\n"
   265    "  parentid INT,\n"
   266    "  childid INT,\n"
   267    "  isExclude BOOLEAN DEFAULT false,\n"
   268    "  PRIMARY KEY(parentid, childid)\n"
   269    ") WITHOUT ROWID;\n"
   270    "CREATE INDEX repo_cherrypick_cid ON repo_cherrypick(childid);\n"
   271    "CREATE TABLE repo_ticket(\n"
   272    "  -- Do not change any column that begins with tkt_\n"
   273    "  tkt_id INTEGER PRIMARY KEY,\n"
   274    "  tkt_uuid TEXT UNIQUE,\n"
   275    "  tkt_mtime DATE,\n"
   276    "  tkt_ctime DATE,\n"
   277    "  -- Add as many fields as required below this line\n"
   278    "  type TEXT,\n"
   279    "  status TEXT,\n"
   280    "  subsystem TEXT,\n"
   281    "  priority TEXT,\n"
   282    "  severity TEXT,\n"
   283    "  foundin TEXT,\n"
   284    "  private_contact TEXT,\n"
   285    "  resolution TEXT,\n"
   286    "  title TEXT,\n"
   287    "  comment TEXT\n"
   288    ");\n"
   289    "CREATE TABLE repo_ticketchng(\n"
   290    "  -- Do not change any column that begins with tkt_\n"
   291    "  tkt_id INTEGER REFERENCES ticket,\n"
   292    "  tkt_rid INTEGER REFERENCES blob,\n"
   293    "  tkt_mtime DATE,\n"
   294    "  -- Add as many fields as required below this line\n"
   295    "  login TEXT,\n"
   296    "  username TEXT,\n"
   297    "  mimetype TEXT,\n"
   298    "  icomment TEXT\n"
   299    ");\n"
   300    "CREATE INDEX repo_ticketchng_idx1 ON repo_ticketchng(tkt_id, tkt_mtime);\n"
   301    "CREATE TRIGGER repo_alert_trigger1\n"
   302    "AFTER INSERT ON repo_event BEGIN\n"
   303    "  INSERT INTO repo_pending_alert(eventid)\n"
   304    "    SELECT printf('%.1c%d',new.type,new.objid) WHERE true\n"
   305    "    ON CONFLICT(eventId) DO NOTHING;\n"
   306    "END;\n"
   307    "CREATE TABLE repo_vcache(\n"
   308    "  vid INTEGER,         -- check-in ID\n"
   309    "  fname TEXT,          -- filename\n"
   310    "  rid INTEGER,         -- artifact ID\n"
   311    "  PRIMARY KEY(vid,fname)\n"
   312    ") WITHOUT ROWID;\n"
   313    "CREATE TABLE localdb_vvar(\n"
   314    "  name TEXT PRIMARY KEY NOT NULL,\n"
   315    "  value CLOB,\n"
   316    "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
   317    ");\n"
   318    "CREATE TABLE localdb_vfile(\n"
   319    "  id INTEGER PRIMARY KEY,\n"
   320    "  vid INTEGER REFERENCES blob,\n"
   321    "  chnged INT DEFAULT 0,\n"
   322    "  deleted BOOLEAN DEFAULT 0,\n"
   323    "  isexe BOOLEAN,\n"
   324    "  islink BOOLEAN,\n"
   325    "  rid INTEGER,\n"
   326    "  mrid INTEGER,\n"
   327    "  mtime INTEGER,\n"
   328    "  pathname TEXT,\n"
   329    "  origname TEXT, mhash,\n"
   330    "  UNIQUE(pathname,vid)\n"
   331    ");\n"
   332    "CREATE TABLE localdb_sqlite_stat1(tbl,idx,stat);\n"
   333    "CREATE TABLE localdb_vcache(\n"
   334    "  vid INTEGER,         -- check-in ID\n"
   335    "  fname TEXT,          -- filename\n"
   336    "  rid INTEGER,         -- artifact ID\n"
   337    "  PRIMARY KEY(vid,fname)\n"
   338    ") WITHOUT ROWID;\n"
   339    "CREATE TABLE localdb_stash(\n"
   340    "  stashid INTEGER PRIMARY KEY,\n"
   341    "  vid INTEGER,\n"
   342    "  hash TEXT,\n"
   343    "  comment TEXT,\n"
   344    "  ctime TIMESTAMP\n"
   345    ");\n"
   346    "CREATE TABLE localdb_stashfile(\n"
   347    "  stashid INTEGER REFERENCES stash,\n"
   348    "  isAdded BOOLEAN,\n"
   349    "  isRemoved BOOLEAN,\n"
   350    "  isExec BOOLEAN,\n"
   351    "  isLink BOOLEAN,\n"
   352    "  rid INTEGER,\n"
   353    "  hash TEXT,\n"
   354    "  origname TEXT,\n"
   355    "  newname TEXT,\n"
   356    "  delta BLOB,\n"
   357    "  PRIMARY KEY(newname, stashid)\n"
   358    ");\n"
   359    "CREATE TABLE localdb_vmerge(\n"
   360    "  id INTEGER REFERENCES vfile,\n"
   361    "  merge INTEGER,\n"
   362    "  mhash TEXT\n"
   363    ");\n"
   364    "CREATE UNIQUE INDEX localdb_vmergex1 ON localdb_vmerge(id,mhash);\n"
   365    "CREATE TRIGGER localdb_vmerge_ck1 AFTER INSERT ON localdb_vmerge\n"
   366    "WHEN new.mhash IS NULL BEGIN\n"
   367    "  SELECT raise(FAIL,\n"
   368    "  'trying to update a newer checkout with an older version of Fossil');\n"
   369    "END;\n"
   370    "CREATE TABLE configdb_global_config(\n"
   371    "  name TEXT PRIMARY KEY,\n"
   372    "  value TEXT\n"
   373    ");\n"
   374    "CREATE TABLE configdb_sqlite_stat1(tbl,idx,stat);\n"
   375  ;
   376  
   377  #ifdef __linux__
   378  #include <sys/types.h>
   379  #include <unistd.h>
   380  
   381  /*
   382  ** Attempt to display I/O stats on Linux using /proc/PID/io
   383  */
   384  static void displayLinuxIoStats(FILE *out){
   385    FILE *in;
   386    char z[200];
   387    sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
   388    in = fopen(z, "rb");
   389    if( in==0 ) return;
   390    while( fgets(z, sizeof(z), in)!=0 ){
   391      static const struct {
   392        const char *zPattern;
   393        const char *zDesc;
   394      } aTrans[] = {
   395        { "rchar: ",                  "Bytes received by read():" },
   396        { "wchar: ",                  "Bytes sent to write():"    },
   397        { "syscr: ",                  "Read() system calls:"      },
   398        { "syscw: ",                  "Write() system calls:"     },
   399        { "read_bytes: ",             "Bytes rcvd from storage:"  },
   400        { "write_bytes: ",            "Bytes sent to storage:"    },
   401        { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
   402      };
   403      int i;
   404      for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
   405        int n = (int)strlen(aTrans[i].zPattern);
   406        if( strncmp(aTrans[i].zPattern, z, n)==0 ){
   407          fprintf(out, "-- %-28s %s", aTrans[i].zDesc, &z[n]);
   408          break;
   409        }
   410      }
   411    }
   412    fclose(in);
   413  }   
   414  #endif
   415  
   416  /*
   417  ** Return the value of a hexadecimal digit.  Return -1 if the input
   418  ** is not a hex digit.
   419  */
   420  static int hexDigitValue(char c){
   421    if( c>='0' && c<='9' ) return c - '0';
   422    if( c>='a' && c<='f' ) return c - 'a' + 10;
   423    if( c>='A' && c<='F' ) return c - 'A' + 10;
   424    return -1;
   425  }
   426  
   427  /*
   428  ** Interpret zArg as an integer value, possibly with suffixes.
   429  */
   430  static int integerValue(const char *zArg){
   431    sqlite3_int64 v = 0;
   432    static const struct { char *zSuffix; int iMult; } aMult[] = {
   433      { "KiB", 1024 },
   434      { "MiB", 1024*1024 },
   435      { "GiB", 1024*1024*1024 },
   436      { "KB",  1000 },
   437      { "MB",  1000000 },
   438      { "GB",  1000000000 },
   439      { "K",   1000 },
   440      { "M",   1000000 },
   441      { "G",   1000000000 },
   442    };
   443    int i;
   444    int isNeg = 0;
   445    if( zArg[0]=='-' ){
   446      isNeg = 1;
   447      zArg++;
   448    }else if( zArg[0]=='+' ){
   449      zArg++;
   450    }
   451    if( zArg[0]=='0' && zArg[1]=='x' ){
   452      int x;
   453      zArg += 2;
   454      while( (x = hexDigitValue(zArg[0]))>=0 ){
   455        v = (v<<4) + x;
   456        zArg++;
   457      }
   458    }else{
   459      while( isdigit(zArg[0]) ){
   460        v = v*10 + zArg[0] - '0';
   461        zArg++;
   462      }
   463    }
   464    for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
   465      if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
   466        v *= aMult[i].iMult;
   467        break;
   468      }
   469    }
   470    if( v>0x7fffffff ){
   471      printf("ERROR: parameter too large - max 2147483648\n");
   472      exit(1);
   473    }
   474    return (int)(isNeg? -v : v);
   475  }
   476  
   477  
   478  int main(int argc, char **argv){
   479    const char *zCmd = 0;
   480    int i;
   481    int bAutovac = 0;
   482    int showStats = 0;
   483    const char *zDbName = "./startup.db";
   484    int nHeap = 0;
   485    int mnHeap = 0;
   486  
   487    for(i=1; i<argc; i++){
   488      const char *z = argv[i];
   489      if( z[0]!='-' ){
   490        if( zCmd ){
   491          usage(argv[0]);
   492        }
   493        zCmd = z;
   494        continue;
   495      }
   496      if( z[1]=='-' ) z++;
   497      if( strcmp(z, "-autovacuum")==0 ){
   498        bAutovac = 1;
   499      }else
   500      if( strcmp(z, "-dbname")==0 ){
   501        if( i==argc-1 ){
   502          printf("ERROR: missing argument on \"%s\"\n", argv[0]);
   503          exit(1);
   504        }
   505        zDbName = argv[++i];
   506      }else
   507      if( strcmp(z,"-heap")==0 ){
   508        if( i>=argc-2 ){
   509          printf("ERROR: missing arguments on %s\n", argv[i]);
   510          exit(1);
   511        }
   512        nHeap = integerValue(argv[i+1]);
   513        mnHeap = integerValue(argv[i+2]);
   514        i += 2;
   515      }else
   516      if( strcmp(z,"-stats")==0 ){
   517         showStats = 1;
   518      }else
   519      {
   520        printf("ERROR: unknown option \"%s\"\n", argv[i]);
   521        usage(argv[0]);
   522      }
   523    }
   524    if( zCmd==0 ){
   525      printf("ERROR: no COMMAND specified\n");
   526      usage(argv[0]);
   527    }
   528    if( strcmp(zCmd, "run")==0 ){
   529      sqlite3 *db;
   530      int rc;
   531      char *zErr = 0;
   532      void *pHeap = 0;
   533      if( nHeap>0 ){
   534        pHeap = malloc( nHeap );
   535        if( pHeap==0 ){
   536          printf("ERROR: cannot allocate %d-byte heap\n", nHeap);
   537          exit(1);
   538        }
   539        rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
   540        if( rc ){
   541          printf("ERROR: heap configuration failed: %d\n", rc);
   542          exit(1);
   543        }
   544      }
   545      rc = sqlite3_open(zDbName, &db);
   546      if( rc ){
   547        printf("SQLite error: %s\n", sqlite3_errmsg(db));
   548      }else{
   549        sqlite3_exec(db, "PRAGMA synchronous", 0, 0, &zErr);
   550      }
   551      if( zErr ){
   552        printf("ERROR: %s\n", zErr);
   553        sqlite3_free(zErr);
   554      }
   555      if( showStats ){
   556        int iCur, iHi;
   557        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
   558        printf("-- Lookaside Slots Used:        %d (max %d)\n", iCur,iHi);
   559        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
   560        printf("-- Successful lookasides:       %d\n", iHi);
   561        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
   562        printf("-- Lookaside size faults:       %d\n", iHi);
   563        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
   564        printf("-- Lookaside OOM faults:        %d\n", iHi);
   565        sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
   566        printf("-- Pager Heap Usage:            %d bytes\n", iCur);
   567        sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
   568        printf("-- Page cache hits:             %d\n", iCur);
   569        sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
   570        printf("-- Page cache misses:           %d\n", iCur);
   571        sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
   572        printf("-- Page cache writes:           %d\n", iCur); 
   573        sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
   574        printf("-- Schema Heap Usage:           %d bytes\n", iCur); 
   575        sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
   576        printf("-- Statement Heap Usage:        %d bytes\n", iCur); 
   577      }
   578      sqlite3_close(db);
   579      free(pHeap);
   580      /* Global memory usage statistics printed after the database connection
   581      ** has closed.  Memory usage should be zero at this point. */
   582      if( showStats ){
   583        int iCur, iHi;
   584        sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
   585        printf("-- Memory Used (bytes):         %d (max %d)\n", iCur,iHi);
   586        sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
   587        printf("-- Outstanding Allocations:     %d (max %d)\n", iCur,iHi);
   588        sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
   589        printf("-- Pcache Overflow Bytes:       %d (max %d)\n", iCur,iHi);
   590        sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
   591        printf("-- Largest Allocation:          %d bytes\n",iHi);
   592        sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
   593        printf("-- Largest Pcache Allocation:   %d bytes\n",iHi);
   594  #ifdef __linux__
   595        displayLinuxIoStats(stdout);
   596  #endif
   597      }
   598      return 0;
   599    }
   600    if( strcmp(zCmd, "init")==0 ){
   601      sqlite3 *db;
   602      char *zAux;
   603      char *zErr = 0;
   604      int rc;
   605      unlink(zDbName);
   606      zAux = sqlite3_mprintf("%s-journal", zDbName);
   607      unlink(zAux);
   608      sqlite3_free(zAux);
   609      zAux = sqlite3_mprintf("%s-wal", zDbName);
   610      unlink(zAux);
   611      sqlite3_free(zAux);
   612      rc = sqlite3_open(zDbName, &db);
   613      if( rc ){
   614        printf("SQLite error: %s\n", sqlite3_errmsg(db));
   615      }else{
   616        sqlite3_exec(db, "BEGIN", 0, 0, 0);
   617        sqlite3_exec(db, zTestSchema, 0, 0, &zErr);
   618        sqlite3_exec(db, "COMMIT", 0, 0, 0);
   619      }
   620      if( zErr ){
   621        printf("ERROR: %s\n", zErr);
   622        sqlite3_free(zErr);
   623      }
   624      sqlite3_close(db);
   625      return 0;
   626  
   627    }
   628  }