struct callback_data {
sqlite3 *db; /* The database */
int echoOn; /* True to echo input commands */
- int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
+ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
int statsOn; /* True to display memory stats before each finalize */
+ int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
FILE *traceOut; /* Output for sqlite3_trace() */
}else if( aiType && aiType[i]==SQLITE_TEXT ){
if( zSep[0] ) fprintf(p->out,"%s",zSep);
output_quoted_string(p->out, azArg[i]);
- }else if( aiType && (aiType[i]==SQLITE_INTEGER || aiType[i]==SQLITE_FLOAT) ){
+ }else if( aiType && (aiType[i]==SQLITE_INTEGER
+ || aiType[i]==SQLITE_FLOAT) ){
fprintf(p->out,"%s%s",zSep, azArg[i]);
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
*/
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
- ".bail ON|OFF Stop after hitting an error. Default OFF\n"
+ ".bail on|off Stop after hitting an error. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
" LIKE pattern TABLE.\n"
- ".echo ON|OFF Turn command echo on or off\n"
+ ".echo on|off Turn command echo on or off\n"
".exit Exit this program\n"
- ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
+ ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n"
" With no args, it turns EXPLAIN on.\n"
- ".headers ON|OFF Turn display of headers on or off\n"
+ ".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"
" tabs Tab-separated values\n"
" tcl TCL list elements\n"
".nullvalue STRING Use STRING in place of NULL values\n"
+ ".once FILENAME Output for the next SQL command only to FILENAME\n"
".open ?FILENAME? Close existing database and reopen FILENAME\n"
- ".output FILENAME Send output to FILENAME\n"
- ".output stdout Send output to the screen\n"
+ ".output ?FILENAME? Send output to FILENAME or stdout\n"
".print STRING... Print literal STRING\n"
".prompt MAIN CONTINUE Replace the standard prompts\n"
".quit Exit this program\n"
".separator STRING Change separator used by output mode and .import\n"
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".show Show the current values for various settings\n"
- ".stats ON|OFF Turn stats on or off\n"
+ ".stats on|off Turn stats on or off\n"
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n"
".timeout MS Try opening locked tables for MS milliseconds\n"
+ ".timer on|off Turn SQL timer on or off\n"
".trace FILE|off Output each SQL statement as it is run\n"
".vfsname ?AUX? Print the name of the VFS stack\n"
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
" Negative values right-justify\n"
;
-static char zTimerHelp[] =
- ".timer ON|OFF Turn the CPU timer measurement on or off\n"
-;
-
/* Forward reference */
static int process_input(struct callback_data *p, FILE *in);
static void resolve_backslashes(char *z){
int i, j;
char c;
+ while( *z && *z!='\\' ) z++;
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' ){
c = z[++i];
}
z[j] = c;
}
- z[j] = 0;
+ if( j<i ) z[j] = 0;
}
/*
sqlite3_close(newDb);
}
+/*
+** Change the output file back to stdout
+*/
+static void output_reset(struct callback_data *p){
+ if( p->outfile[0]=='|' ){
+ pclose(p->out);
+ }else{
+ output_file_close(p->out);
+ }
+ p->outfile[0] = 0;
+ p->out = stdout;
+}
+
/*
** If an input line begins with "." then invoke this routine to
** process that line.
sqlite3_close(pDest);
}else
- if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){
- bail_on_error = booleanValue(azArg[1]);
+ if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
+ if( nArg==2 ){
+ bail_on_error = booleanValue(azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .bail on|off\n");
+ rc = 1;
+ }
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
test_breakpoint();
}else
- if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
- tryToClone(p, azArg[1]);
+ if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
+ if( nArg==2 ){
+ tryToClone(p, azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .clone FILENAME\n");
+ rc = 1;
+ }
}else
- if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
+ if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
struct callback_data data;
char *zErrMsg = 0;
open_db(p, 0);
}
}else
- if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
+ 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
** which causes immediate foreign key constraints to be violated.
** So disable foreign-key constraint enforcement to prevent problems. */
+ if( nArg!=1 && nArg!=2 ){
+ fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
fprintf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
}else
- if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
- p->echoOn = booleanValue(azArg[1]);
+ if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
+ if( nArg==2 ){
+ p->echoOn = booleanValue(azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .echo on|off\n");
+ rc = 1;
+ }
}else
- if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
- p->autoEQP = booleanValue(azArg[1]);
+ if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
+ if( nArg==2 ){
+ p->autoEQP = booleanValue(azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .eqp on|off\n");
+ rc = 1;
+ }
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
rc = 2;
}else
- if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
+ if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
if(val == 1) {
if(!p->explainPrev.valid) {
}
}else
- if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
- strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){
- p->showHeader = booleanValue(azArg[1]);
+ if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
+ if( nArg==2 ){
+ p->showHeader = booleanValue(azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .headers on|off\n");
+ rc = 1;
+ }
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
- fprintf(stderr,"%s",zHelp);
- if( HAS_TIMER ){
- fprintf(stderr,"%s",zTimerHelp);
- }
+ fprintf(p->out, "%s", zHelp);
}else
- if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
+ if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
char *zTable = azArg[2]; /* Insert data into this table */
char *zFile = azArg[1]; /* Name of file to extra content from */
sqlite3_stmt *pStmt = NULL; /* A statement */
CSVReader sCsv; /* Reader context */
int (*xCloser)(FILE*); /* Procedure to close th3 connection */
+ if( nArg!=3 ){
+ fprintf(stderr, "Usage: .import FILE TABLE\n");
+ goto meta_command_exit;
+ }
seenInterrupt = 0;
memset(&sCsv, 0, sizeof(sCsv));
open_db(p, 0);
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
}else
- if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
+ if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
struct callback_data data;
char *zErrMsg = 0;
open_db(p, 0);
"ORDER BY 1",
callback, &data, &zErrMsg
);
- }else{
+ }else if( nArg==2 ){
zShellStatic = azArg[1];
rc = sqlite3_exec(p->db,
"SELECT name FROM sqlite_master "
callback, &data, &zErrMsg
);
zShellStatic = 0;
+ }else{
+ fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
+ rc = 1;
+ goto meta_command_exit;
}
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
- if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
+ if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
const char *zFile, *zProc;
char *zErrMsg = 0;
+ if( nArg<2 ){
+ fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
zFile = azArg[1];
zProc = nArg>=3 ? azArg[2] : 0;
open_db(p, 0);
}else
#endif
- if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){
- const char *zFile = azArg[1];
- output_file_close(p->pLog);
- p->pLog = output_file_open(zFile);
+ if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
+ if( nArg!=2 ){
+ fprintf(stderr, "Usage: .log FILENAME\n");
+ rc = 1;
+ }else{
+ const char *zFile = azArg[1];
+ output_file_close(p->pLog);
+ p->pLog = output_file_open(zFile);
+ }
}else
- if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
- int n2 = strlen30(azArg[1]);
- if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
- ||
- (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){
+ if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
+ const char *zMode = nArg>=2 ? azArg[1] : "";
+ int n2 = (int)strlen(zMode);
+ int c2 = zMode[0];
+ if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
p->mode = MODE_Line;
- }else if( (n2==6 && strncmp(azArg[1],"column",n2)==0)
- ||
- (n2==7 && strncmp(azArg[1],"columns",n2)==0) ){
+ }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
p->mode = MODE_Column;
- }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){
+ }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
p->mode = MODE_List;
- }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){
+ }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
p->mode = MODE_Html;
- }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
+ }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
p->mode = MODE_Tcl;
sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
- }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
+ }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
- }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
+ }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
- }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
+ }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
p->mode = MODE_Insert;
- set_table_name(p, "table");
+ set_table_name(p, nArg>=3 ? azArg[2] : "table");
}else {
fprintf(stderr,"Error: mode should be one of: "
"column csv html insert line list tabs tcl\n");
}
}else
- if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){
- int n2 = strlen30(azArg[1]);
- if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
- p->mode = MODE_Insert;
- set_table_name(p, azArg[2]);
- }else {
- fprintf(stderr, "Error: invalid arguments: "
- " \"%s\". Enter \".help\" for help\n", azArg[2]);
+ if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
+ if( nArg==2 ){
+ sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
+ "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .nullvalue STRING\n");
rc = 1;
}
}else
- if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
- sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
- "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
- }else
-
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
sqlite3 *savedDb = p->db;
const char *zSavedFilename = p->zDbFilename;
}
}else
- if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
- if( p->outfile[0]=='|' ){
- pclose(p->out);
+ if( c=='o'
+ && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
+ ){
+ const char *zFile = nArg>=2 ? azArg[1] : "stdout";
+ if( nArg>2 ){
+ fprintf(stderr, "Usage: .%s FILE\n", azArg[0]);
+ rc = 1;
+ goto meta_command_exit;
+ }
+ if( n>1 && strncmp(azArg[0], "once", n)==0 ){
+ if( nArg<2 ){
+ fprintf(stderr, "Usage: .once FILE\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ p->outCount = 2;
}else{
- output_file_close(p->out);
+ p->outCount = 0;
}
- p->outfile[0] = 0;
- if( azArg[1][0]=='|' ){
- p->out = popen(&azArg[1][1], "w");
+ output_reset(p);
+ if( zFile[0]=='|' ){
+ p->out = popen(zFile + 1, "w");
if( p->out==0 ){
- fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]);
+ fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
p->out = stdout;
rc = 1;
}else{
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
+ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}else{
- p->out = output_file_open(azArg[1]);
+ p->out = output_file_open(zFile);
if( p->out==0 ){
- if( strcmp(azArg[1],"off")!=0 ){
- fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
+ if( strcmp(zFile,"off")!=0 ){
+ fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
}
p->out = stdout;
rc = 1;
} else {
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
+ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
}
}
}else
fprintf(p->out, "\n");
}else
- if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
+ if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
if( nArg >= 2) {
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
}
}
}else
- if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){
+ if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
rc = 2;
}else
- if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
- FILE *alt = fopen(azArg[1], "rb");
+ if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
+ FILE *alt;
+ if( nArg!=2 ){
+ fprintf(stderr, "Usage: .read FILE\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ alt = fopen(azArg[1], "rb");
if( alt==0 ){
fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}
}else
- if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){
+ if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
const char *zSrcFile;
const char *zDb;
sqlite3 *pSrc;
if( nArg==2 ){
zSrcFile = azArg[1];
zDb = "main";
- }else{
+ }else if( nArg==3 ){
zSrcFile = azArg[2];
zDb = azArg[1];
+ }else{
+ fprintf(stderr, "Usage: .restore ?DB? FILE\n");
+ rc = 1;
+ goto meta_command_exit;
}
rc = sqlite3_open(zSrcFile, &pSrc);
if( rc!=SQLITE_OK ){
sqlite3_close(pSrc);
}else
- if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){
+ if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
struct callback_data data;
char *zErrMsg = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.mode = MODE_Semi;
- if( nArg>1 ){
+ if( nArg==2 ){
int i;
for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
if( strcmp(azArg[1],"sqlite_master")==0 ){
callback, &data, &zErrMsg);
zShellStatic = 0;
}
- }else{
+ }else if( nArg==1 ){
rc = sqlite3_exec(p->db,
"SELECT sql FROM "
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
"ORDER BY rowid",
callback, &data, &zErrMsg
);
+ }else{
+ fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
+ rc = 1;
+ goto meta_command_exit;
}
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
for(i=1; i<nArg; i++){
char zBuf[200];
v = integerValue(azArg[i]);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%s: %lld 0x%llx\n", azArg[i], v, v);
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
fprintf(p->out, "%s", zBuf);
}
}
}else
#endif
- if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
- sqlite3_snprintf(sizeof(p->separator), p->separator,
- "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
+ if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
+ if( nArg==2 ){
+ sqlite3_snprintf(sizeof(p->separator), p->separator,
+ "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .separator STRING\n");
+ rc = 1;
+ }
}else
if( c=='s'
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
- && nArg>=2
){
char *zCmd;
int i;
+ if( nArg<2 ){
+ fprintf(stderr, "Usage: .system COMMAND\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
for(i=2; i<nArg; i++){
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
sqlite3_free(zCmd);
}else
- if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
+ if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
int i;
+ if( nArg!=1 ){
+ fprintf(stderr, "Usage: .show\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
fprintf(p->out,"\n");
}else
- if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
- p->statsOn = booleanValue(azArg[1]);
+ if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
+ if( nArg==2 ){
+ p->statsOn = booleanValue(azArg[1]);
+ }else{
+ fprintf(stderr, "Usage: .stats on|off\n");
+ rc = 1;
+ }
}else
- if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
+ if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
sqlite3_stmt *pStmt;
char **azResult;
int nRow, nAlloc;
}
}else
- if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
+ if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
open_db(p, 0);
- sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1]));
+ sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
}else
- if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
- && nArg==2
- ){
- enableTimer = booleanValue(azArg[1]);
+ if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
+ if( nArg==2 ){
+ enableTimer = booleanValue(azArg[1]);
+ if( enableTimer && !HAS_TIMER ){
+ fprintf(stderr, "Error: timer not available on this system.\n");
+ enableTimer = 0;
+ }
+ }else{
+ fprintf(stderr, "Usage: .timer on|off\n");
+ rc = 1;
+ }
}else
- if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){
+ if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
open_db(p, 0);
output_file_close(p->traceOut);
+ if( nArg!=2 ){
+ fprintf(stderr, "Usage: .trace FILE|off\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
p->traceOut = output_file_open(azArg[1]);
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
extern int sqlite3WhereTrace;
- sqlite3WhereTrace = booleanValue(azArg[1]);
+ sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
}else
#endif
- if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
+ if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
int j;
assert( nArg<=ArraySize(azArg) );
for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
rc = 1;
}
+meta_command_exit:
+ if( p->outCount ){
+ p->outCount--;
+ if( p->outCount==0 ) output_reset(p);
+ }
return rc;
}
errCnt++;
}
nSql = 0;
+ if( p->outCount ){
+ output_reset(p);
+ p->outCount = 0;
+ }
}else if( nSql && _all_whitespace(zSql) ){
if( p->echoOn ) printf("%s\n", zSql);
nSql = 0;
# .bail ON|OFF Stop after hitting an error. Default OFF
do_test shell1-3.2.1 {
catchcmd "test.db" ".bail"
-} {1 {Error: unknown command or invalid arguments: "bail". Enter ".help" for help}}
+} {1 {Usage: .bail on|off}}
do_test shell1-3.2.2 {
catchcmd "test.db" ".bail ON"
} {0 {}}
do_test shell1-3.2.4 {
# too many arguments
catchcmd "test.db" ".bail OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "bail". Enter ".help" for help}}
+} {1 {Usage: .bail on|off}}
# .databases List names and files of attached databases
do_test shell1-3.3.1 {
catchcmd "-csv test.db" ".databases"
} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
do_test shell1-3.3.2 {
- # too many arguments
+ # extra arguments ignored
catchcmd "test.db" ".databases BAD"
-} {1 {Error: unknown command or invalid arguments: "databases". Enter ".help" for help}}
+} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
# .dump ?TABLE? ... Dump the database in an SQL text format
# If TABLE specified, only dump tables matching
do_test shell1-3.4.3 {
# too many arguments
catchcmd "test.db" ".dump FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "dump". Enter ".help" for help}}
+} {1 {Usage: .dump ?LIKE-PATTERN?}}
# .echo ON|OFF Turn command echo on or off
do_test shell1-3.5.1 {
catchcmd "test.db" ".echo"
-} {1 {Error: unknown command or invalid arguments: "echo". Enter ".help" for help}}
+} {1 {Usage: .echo on|off}}
do_test shell1-3.5.2 {
catchcmd "test.db" ".echo ON"
} {0 {}}
do_test shell1-3.5.4 {
# too many arguments
catchcmd "test.db" ".echo OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "echo". Enter ".help" for help}}
+} {1 {Usage: .echo on|off}}
# .exit Exit this program
do_test shell1-3.6.1 {
catchcmd "test.db" ".explain OFF"
} {0 {}}
do_test shell1-3.7.4 {
- # too many arguments
+ # extra arguments ignored
catchcmd "test.db" ".explain OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "explain". Enter ".help" for help}}
+} {0 {}}
# .header(s) ON|OFF Turn display of headers on or off
do_test shell1-3.9.1 {
catchcmd "test.db" ".header"
-} {1 {Error: unknown command or invalid arguments: "header". Enter ".help" for help}}
+} {1 {Usage: .headers on|off}}
do_test shell1-3.9.2 {
catchcmd "test.db" ".header ON"
} {0 {}}
do_test shell1-3.9.4 {
# too many arguments
catchcmd "test.db" ".header OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "header". Enter ".help" for help}}
+} {1 {Usage: .headers on|off}}
do_test shell1-3.9.5 {
catchcmd "test.db" ".headers"
-} {1 {Error: unknown command or invalid arguments: "headers". Enter ".help" for help}}
+} {1 {Usage: .headers on|off}}
do_test shell1-3.9.6 {
catchcmd "test.db" ".headers ON"
} {0 {}}
do_test shell1-3.9.8 {
# too many arguments
catchcmd "test.db" ".headers OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "headers". Enter ".help" for help}}
+} {1 {Usage: .headers on|off}}
# .help Show this message
do_test shell1-3.10.1 {
# .import FILE TABLE Import data from FILE into TABLE
do_test shell1-3.11.1 {
catchcmd "test.db" ".import"
-} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
+} {1 {Usage: .import FILE TABLE}}
do_test shell1-3.11.2 {
catchcmd "test.db" ".import FOO"
-} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
+} {1 {Usage: .import FILE TABLE}}
#do_test shell1-3.11.2 {
# catchcmd "test.db" ".import FOO BAR"
#} {1 {Error: no such table: BAR}}
do_test shell1-3.11.3 {
# too many arguments
catchcmd "test.db" ".import FOO BAR BAD"
-} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
+} {1 {Usage: .import FILE TABLE}}
# .indices ?TABLE? Show names of all indices
# If TABLE specified, only show indices for tables
do_test shell1-3.12.3 {
# too many arguments
catchcmd "test.db" ".indices FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "indices". Enter ".help" for help}}
+} {1 {Usage: .indices ?LIKE-PATTERN?}}
# .mode MODE ?TABLE? Set output mode where MODE is one of:
# csv Comma-separated values
# tcl TCL list elements
do_test shell1-3.13.1 {
catchcmd "test.db" ".mode"
-} {1 {Error: unknown command or invalid arguments: "mode". Enter ".help" for help}}
+} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.2 {
catchcmd "test.db" ".mode FOO"
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
catchcmd "test.db" ".mode tcl"
} {0 {}}
do_test shell1-3.13.11 {
- # too many arguments
+ # extra arguments ignored
catchcmd "test.db" ".mode tcl BAD"
-} {1 {Error: invalid arguments: "BAD". Enter ".help" for help}}
+} {0 {}}
# don't allow partial mode type matches
do_test shell1-3.13.12 {
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
do_test shell1-3.13.14 {
catchcmd "test.db" ".mode lin"
-} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
+} {0 {}}
# .nullvalue STRING Print STRING in place of NULL values
do_test shell1-3.14.1 {
catchcmd "test.db" ".nullvalue"
-} {1 {Error: unknown command or invalid arguments: "nullvalue". Enter ".help" for help}}
+} {1 {Usage: .nullvalue STRING}}
do_test shell1-3.14.2 {
catchcmd "test.db" ".nullvalue FOO"
} {0 {}}
do_test shell1-3.14.3 {
# too many arguments
catchcmd "test.db" ".nullvalue FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "nullvalue". Enter ".help" for help}}
+} {1 {Usage: .nullvalue STRING}}
# .output FILENAME Send output to FILENAME
do_test shell1-3.15.1 {
catchcmd "test.db" ".output"
-} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
+} {0 {}}
do_test shell1-3.15.2 {
catchcmd "test.db" ".output FOO"
} {0 {}}
do_test shell1-3.15.3 {
# too many arguments
catchcmd "test.db" ".output FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
+} {1 {Usage: .output FILE}}
# .output stdout Send output to the screen
do_test shell1-3.16.1 {
do_test shell1-3.16.2 {
# too many arguments
catchcmd "test.db" ".output stdout BAD"
-} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
+} {1 {Usage: .output FILE}}
# .prompt MAIN CONTINUE Replace the standard prompts
do_test shell1-3.17.1 {
catchcmd "test.db" ".prompt"
-} {1 {Error: unknown command or invalid arguments: "prompt". Enter ".help" for help}}
+} {0 {}}
do_test shell1-3.17.2 {
catchcmd "test.db" ".prompt FOO"
} {0 {}}
do_test shell1-3.17.4 {
# too many arguments
catchcmd "test.db" ".prompt FOO BAR BAD"
-} {1 {Error: unknown command or invalid arguments: "prompt". Enter ".help" for help}}
+} {0 {}}
# .quit Exit this program
do_test shell1-3.18.1 {
do_test shell1-3.18.2 {
# too many arguments
catchcmd "test.db" ".quit BAD"
-} {1 {Error: unknown command or invalid arguments: "quit". Enter ".help" for help}}
+} {0 {}}
# .read FILENAME Execute SQL in FILENAME
do_test shell1-3.19.1 {
catchcmd "test.db" ".read"
-} {1 {Error: unknown command or invalid arguments: "read". Enter ".help" for help}}
+} {1 {Usage: .read FILE}}
do_test shell1-3.19.2 {
forcedelete FOO
catchcmd "test.db" ".read FOO"
do_test shell1-3.19.3 {
# too many arguments
catchcmd "test.db" ".read FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "read". Enter ".help" for help}}
+} {1 {Usage: .read FILE}}
# .restore ?DB? FILE Restore content of DB (default "main") from FILE
do_test shell1-3.20.1 {
catchcmd "test.db" ".restore"
-} {1 {Error: unknown command or invalid arguments: "restore". Enter ".help" for help}}
+} {1 {Usage: .restore ?DB? FILE}}
do_test shell1-3.20.2 {
catchcmd "test.db" ".restore FOO"
} {0 {}}
do_test shell1-3.20.4 {
# too many arguments
catchcmd "test.db" ".restore FOO BAR BAD"
-} {1 {Error: unknown command or invalid arguments: "restore". Enter ".help" for help}}
+} {1 {Usage: .restore ?DB? FILE}}
# .schema ?TABLE? Show the CREATE statements
# If TABLE specified, only show tables matching
do_test shell1-3.21.3 {
# too many arguments
catchcmd "test.db" ".schema FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "schema". Enter ".help" for help}}
+} {1 {Usage: .schema ?LIKE-PATTERN?}}
do_test shell1-3.21.4 {
catchcmd "test.db" {
# .separator STRING Change separator used by output mode and .import
do_test shell1-3.22.1 {
catchcmd "test.db" ".separator"
-} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
+} {1 {Usage: .separator STRING}}
do_test shell1-3.22.2 {
catchcmd "test.db" ".separator FOO"
} {0 {}}
do_test shell1-3.22.3 {
# too many arguments
catchcmd "test.db" ".separator FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
+} {1 {Usage: .separator STRING}}
# .show Show the current values for various settings
do_test shell1-3.23.1 {
do_test shell1-3.23.2 {
# too many arguments
catchcmd "test.db" ".show BAD"
-} {1 {Error: unknown command or invalid arguments: "show". Enter ".help" for help}}
+} {1 {Usage: .show}}
# .stats ON|OFF Turn stats on or off
do_test shell1-3.23b.1 {
catchcmd "test.db" ".stats"
-} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
+} {1 {Usage: .stats on|off}}
do_test shell1-3.23b.2 {
catchcmd "test.db" ".stats ON"
} {0 {}}
do_test shell1-3.23b.4 {
# too many arguments
catchcmd "test.db" ".stats OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
+} {1 {Usage: .stats on|off}}
# .tables ?TABLE? List names of tables
# If TABLE specified, only list tables matching
do_test shell1-3.24.3 {
# too many arguments
catchcmd "test.db" ".tables FOO BAD"
-} {1 {Error: unknown command or invalid arguments: "tables". Enter ".help" for help}}
+} {0 {}}
# .timeout MS Try opening locked tables for MS milliseconds
do_test shell1-3.25.1 {
catchcmd "test.db" ".timeout"
-} {1 {Error: unknown command or invalid arguments: "timeout". Enter ".help" for help}}
+} {0 {}}
do_test shell1-3.25.2 {
catchcmd "test.db" ".timeout zzz"
# this should be treated the same as a '0' timeout
do_test shell1-3.25.4 {
# too many arguments
catchcmd "test.db" ".timeout 1 BAD"
-} {1 {Error: unknown command or invalid arguments: "timeout". Enter ".help" for help}}
+} {0 {}}
# .width NUM NUM ... Set column widths for "column" mode
do_test shell1-3.26.1 {
catchcmd "test.db" ".width"
-} {1 {Error: unknown command or invalid arguments: "width". Enter ".help" for help}}
+} {0 {}}
do_test shell1-3.26.2 {
catchcmd "test.db" ".width xxx"
# this should be treated the same as a '0' width for col 1
# .timer ON|OFF Turn the CPU timer measurement on or off
do_test shell1-3.27.1 {
catchcmd "test.db" ".timer"
-} {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}}
+} {1 {Usage: .timer on|off}}
do_test shell1-3.27.2 {
catchcmd "test.db" ".timer ON"
} {0 {}}
do_test shell1-3.27.4 {
# too many arguments
catchcmd "test.db" ".timer OFF BAD"
-} {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}}
+} {1 {Usage: .timer on|off}}
do_test shell1-3-28.1 {
catchcmd test.db \