aboutsummaryrefslogtreecommitdiff
path: root/src/shell.c
diff options
context:
space:
mode:
authormistachkin <mistachkin@noemail.net>2015-02-27 19:40:08 +0000
committermistachkin <mistachkin@noemail.net>2015-02-27 19:40:08 +0000
commit0404e74caa95a4cde7bdba71ad95d6eb8f924c01 (patch)
treec0bcde754c3ce16edbf06bfda8d4f0b058054fb5 /src/shell.c
parentbfefa4c27b42b74e6b1685a3c93585fd0fa7d666 (diff)
parent22ec13466cbc6ce4f3cc642e5c23c5d52dcace27 (diff)
downloadsqlite-0404e74caa95a4cde7bdba71ad95d6eb8f924c01.tar.gz
sqlite-0404e74caa95a4cde7bdba71ad95d6eb8f924c01.zip
Merge updates from trunk.
FossilOrigin-Name: acf7684323da4dc3aaf9746bd13b0f56054a17dd
Diffstat (limited to 'src/shell.c')
-rw-r--r--src/shell.c197
1 files changed, 172 insertions, 25 deletions
diff --git a/src/shell.c b/src/shell.c
index b7fa627bf..3099c1eda 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -59,18 +59,38 @@
# include <readline/readline.h>
# include <readline/history.h>
#endif
+
#if HAVE_EDITLINE
-# undef HAVE_READLINE
-# define HAVE_READLINE 1
# include <editline/readline.h>
#endif
-#if !HAVE_READLINE
-# define add_history(X)
-# define read_history(X)
-# define write_history(X)
-# define stifle_history(X)
+
+#if HAVE_EDITLINE || HAVE_READLINE
+
+# define shell_add_history(X) add_history(X)
+# define shell_read_history(X) read_history(X)
+# define shell_write_history(X) write_history(X)
+# define shell_stifle_history(X) stifle_history(X)
+# define shell_readline(X) readline(X)
+
+#elif HAVE_LINENOISE
+
+# include "linenoise.h"
+# define shell_add_history(X) linenoiseHistoryAdd(X)
+# define shell_read_history(X) linenoiseHistoryLoad(X)
+# define shell_write_history(X) linenoiseHistorySave(X)
+# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
+# define shell_readline(X) linenoise(X)
+
+#else
+
+# define shell_read_history(X)
+# define shell_write_history(X)
+# define shell_stifle_history(X)
+
+# define SHELL_USE_LOCAL_GETLINE 1
#endif
+
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
# include <fcntl.h>
@@ -113,11 +133,11 @@ extern int pclose(FILE*);
** routines take care of that.
*/
#if defined(_WIN32) || defined(WIN32)
-static setBinaryMode(FILE *out){
+static void setBinaryMode(FILE *out){
fflush(out);
_setmode(_fileno(out), _O_BINARY);
}
-static setTextMode(FILE *out){
+static void setTextMode(FILE *out){
fflush(out);
_setmode(_fileno(out), _O_TEXT);
}
@@ -451,14 +471,14 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
-#if HAVE_READLINE
- free(zPrior);
- zResult = readline(zPrompt);
- if( zResult && *zResult ) add_history(zResult);
-#else
+#if SHELL_USE_LOCAL_GETLINE
printf("%s", zPrompt);
fflush(stdout);
zResult = local_getline(zPrior, stdin);
+#else
+ free(zPrior);
+ zResult = shell_readline(zPrompt);
+ if( zResult && *zResult ) shell_add_history(zResult);
#endif
}
return zResult;
@@ -1734,6 +1754,7 @@ static char zHelp[] =
".binary on|off Turn binary output on or off. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
+ ".dbinfo ?DB? Show status information about the database\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
" LIKE pattern TABLE.\n"
@@ -1746,8 +1767,8 @@ static char zHelp[] =
".headers on|off Turn display of headers on or off\n"
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
- ".indices ?TABLE? Show names of all indices\n"
- " If TABLE specified, only show indices for tables\n"
+ ".indexes ?TABLE? Show names of all indexes\n"
+ " If TABLE specified, only show indexes for tables\n"
" matching LIKE pattern TABLE.\n"
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
@@ -2446,6 +2467,115 @@ static void output_reset(ShellState *p){
}
/*
+** Run an SQL command and return the single integer result.
+*/
+static int db_int(ShellState *p, const char *zSql){
+ sqlite3_stmt *pStmt;
+ int res = 0;
+ sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
+ res = sqlite3_column_int(pStmt,0);
+ }
+ sqlite3_finalize(pStmt);
+ return res;
+}
+
+/*
+** Convert a 2-byte or 4-byte big-endian integer into a native integer
+*/
+unsigned int get2byteInt(unsigned char *a){
+ return (a[0]<<8) + a[1];
+}
+unsigned int get4byteInt(unsigned char *a){
+ return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
+}
+
+/*
+** Implementation of the ".info" command.
+**
+** Return 1 on error, 2 to exit, and 0 otherwise.
+*/
+static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
+ static const struct { const char *zName; int ofst; } aField[] = {
+ { "file change counter:", 24 },
+ { "database page count:", 28 },
+ { "freelist page count:", 36 },
+ { "schema cookie:", 40 },
+ { "schema format:", 44 },
+ { "default cache size:", 48 },
+ { "autovacuum top root:", 52 },
+ { "incremental vacuum:", 64 },
+ { "text encoding:", 56 },
+ { "user version:", 60 },
+ { "application id:", 68 },
+ { "software version:", 96 },
+ };
+ static const struct { const char *zName; const char *zSql; } aQuery[] = {
+ { "number of tables:",
+ "SELECT count(*) FROM %s WHERE type='table'" },
+ { "number of indexes:",
+ "SELECT count(*) FROM %s WHERE type='index'" },
+ { "number of triggers:",
+ "SELECT count(*) FROM %s WHERE type='trigger'" },
+ { "number of views:",
+ "SELECT count(*) FROM %s WHERE type='view'" },
+ { "schema size:",
+ "SELECT total(length(sql)) FROM %s" },
+ };
+ sqlite3_file *pFile;
+ int i;
+ char *zSchemaTab;
+ char *zDb = nArg>=2 ? azArg[1] : "main";
+ unsigned char aHdr[100];
+ open_db(p, 0);
+ if( p->db==0 ) return 1;
+ sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
+ if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
+ return 1;
+ }
+ i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
+ if( i!=SQLITE_OK ){
+ fprintf(stderr, "unable to read database header\n");
+ return 1;
+ }
+ i = get2byteInt(aHdr+16);
+ if( i==1 ) i = 65536;
+ fprintf(p->out, "%-20s %d\n", "database page size:", i);
+ fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
+ fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
+ fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
+ for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
+ int ofst = aField[i].ofst;
+ unsigned int val = get4byteInt(aHdr + ofst);
+ fprintf(p->out, "%-20s %u", aField[i].zName, val);
+ switch( ofst ){
+ case 56: {
+ if( val==1 ) fprintf(p->out, " (utf8)");
+ if( val==2 ) fprintf(p->out, " (utf16le)");
+ if( val==3 ) fprintf(p->out, " (utf16be)");
+ }
+ }
+ fprintf(p->out, "\n");
+ }
+ if( zDb==0 ){
+ zSchemaTab = sqlite3_mprintf("main.sqlite_master");
+ }else if( strcmp(zDb,"temp")==0 ){
+ zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
+ }else{
+ zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
+ }
+ for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
+ char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
+ int val = db_int(p, zSql);
+ sqlite3_free(zSql);
+ fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
+ }
+ sqlite3_free(zSchemaTab);
+ return 0;
+}
+
+
+/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
@@ -2600,6 +2730,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
+ if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
+ rc = shell_dbinfo_command(p, nArg, azArg);
+ }else
+
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
open_db(p, 0);
/* When playing back a "dump", the content might appear in an order
@@ -2939,7 +3073,7 @@ static int do_meta_command(char *zLine, ShellState *p){
fprintf(stderr, "%s:%d: expected %d columns but found %d - "
"filling the rest with NULL\n",
sCtx.zFile, startLine, nCol, i+1);
- i++;
+ i += 2;
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
}
}
@@ -2968,7 +3102,8 @@ static int do_meta_command(char *zLine, ShellState *p){
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
}else
- if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
+ if( c=='i' && (strncmp(azArg[0], "indices", n)==0
+ || strncmp(azArg[0], "indexes", n)==0) ){
ShellState data;
char *zErrMsg = 0;
open_db(p, 0);
@@ -2998,7 +3133,7 @@ static int do_meta_command(char *zLine, ShellState *p){
);
zShellStatic = 0;
}else{
- fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
+ fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
@@ -3361,7 +3496,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
extern int sqlite3SelectTrace;
- sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
+ sqlite3SelectTrace = integerValue(azArg[1]);
}else
#endif
@@ -3568,6 +3703,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
+ { "imposter", SQLITE_TESTCTRL_IMPOSTER },
};
int testctrl = -1;
int rc = 0;
@@ -3660,6 +3796,18 @@ static int do_meta_command(char *zLine, ShellState *p){
break;
#endif
+ case SQLITE_TESTCTRL_IMPOSTER:
+ if( nArg==5 ){
+ rc = sqlite3_test_control(testctrl, p->db,
+ azArg[2],
+ integerValue(azArg[3]),
+ integerValue(azArg[4]));
+ }else{
+ fprintf(stderr,"Usage: .testctrl initmode dbName onoff tnum\n");
+ rc = 1;
+ }
+ break;
+
case SQLITE_TESTCTRL_BITVEC_TEST:
case SQLITE_TESTCTRL_FAULT_INSTALL:
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
@@ -4227,6 +4375,7 @@ int main(int argc, char **argv){
}
#endif
setBinaryMode(stdin);
+ setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
Argv0 = argv[0];
main_init(&data);
stdin_is_interactive = isatty(0);
@@ -4539,13 +4688,11 @@ int main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
-#if HAVE_READLINE
- if( zHistory ) read_history(zHistory);
-#endif
+ if( zHistory ) shell_read_history(zHistory);
rc = process_input(&data, 0);
if( zHistory ){
- stifle_history(100);
- write_history(zHistory);
+ shell_stifle_history(100);
+ shell_write_history(zHistory);
free(zHistory);
}
}else{