** Implementation of the ".info" command. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */
| 4945 | ** Return 1 on error, 2 to exit, and 0 otherwise. |
| 4946 | */ |
| 4947 | static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ |
| 4948 | static const struct { const char *zName; int ofst; } aField[] = { |
| 4949 | { "file change counter:", 24 }, |
| 4950 | { "database page count:", 28 }, |
| 4951 | { "freelist page count:", 36 }, |
| 4952 | { "schema cookie:", 40 }, |
| 4953 | { "schema format:", 44 }, |
| 4954 | { "default cache size:", 48 }, |
| 4955 | { "autovacuum top root:", 52 }, |
| 4956 | { "incremental vacuum:", 64 }, |
| 4957 | { "text encoding:", 56 }, |
| 4958 | { "user version:", 60 }, |
| 4959 | { "application id:", 68 }, |
| 4960 | { "software version:", 96 }, |
| 4961 | }; |
| 4962 | static const struct { const char *zName; const char *zSql; } aQuery[] = { |
| 4963 | { "number of tables:", |
| 4964 | "SELECT count(*) FROM %s WHERE type='table'" }, |
| 4965 | { "number of indexes:", |
| 4966 | "SELECT count(*) FROM %s WHERE type='index'" }, |
| 4967 | { "number of triggers:", |
| 4968 | "SELECT count(*) FROM %s WHERE type='trigger'" }, |
| 4969 | { "number of views:", |
| 4970 | "SELECT count(*) FROM %s WHERE type='view'" }, |
| 4971 | { "schema size:", |
| 4972 | "SELECT total(length(sql)) FROM %s" }, |
| 4973 | }; |
| 4974 | int i; |
| 4975 | char *zSchemaTab; |
| 4976 | char *zDb = nArg>=2 ? azArg[1] : "main"; |
| 4977 | sqlite3_stmt *pStmt = 0; |
| 4978 | unsigned char aHdr[100]; |
| 4979 | open_db(p, 0); |
| 4980 | if( p->db==0 ) return 1; |
| 4981 | sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", |
| 4982 | -1, &pStmt, 0); |
| 4983 | sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); |
| 4984 | if( sqlite3_step(pStmt)==SQLITE_ROW |
| 4985 | && sqlite3_column_bytes(pStmt,0)>100 |
| 4986 | ){ |
| 4987 | memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100); |
| 4988 | sqlite3_finalize(pStmt); |
| 4989 | }else{ |
| 4990 | raw_printf(stderr, "unable to read database header\n"); |
| 4991 | sqlite3_finalize(pStmt); |
| 4992 | return 1; |
| 4993 | } |
| 4994 | i = get2byteInt(aHdr+16); |
| 4995 | if( i==1 ) i = 65536; |
| 4996 | utf8_printf(p->out, "%-20s %d\n", "database page size:", i); |
| 4997 | utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); |
| 4998 | utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); |
| 4999 | utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); |
| 5000 | for(i=0; i<ArraySize(aField); i++){ |
| 5001 | int ofst = aField[i].ofst; |
| 5002 | unsigned int val = get4byteInt(aHdr + ofst); |
| 5003 | utf8_printf(p->out, "%-20s %u", aField[i].zName, val); |
| 5004 | switch( ofst ){ |
no test coverage detected