mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-03 16:53:36 +03:00
Improvements to error messages for errors in the dot-commands of the
command-line shell. Add the ".once" command. The output of ".help" now goes to the designated output channel. FossilOrigin-Name: 48dce821a07ac29da6ce05e92cf3f6e52b6eb388
This commit is contained in:
337
src/shell.c
337
src/shell.c
@@ -446,8 +446,9 @@ struct previous_mode_data {
|
||||
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() */
|
||||
@@ -878,7 +879,8 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
|
||||
}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);
|
||||
@@ -1570,17 +1572,17 @@ static int run_schema_dump_query(
|
||||
*/
|
||||
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"
|
||||
@@ -1603,9 +1605,9 @@ static char zHelp[] =
|
||||
" 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"
|
||||
@@ -1618,22 +1620,19 @@ static char zHelp[] =
|
||||
".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);
|
||||
|
||||
@@ -1675,6 +1674,7 @@ static void open_db(struct callback_data *p, int keepAlive){
|
||||
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];
|
||||
@@ -1700,7 +1700,7 @@ static void resolve_backslashes(char *z){
|
||||
}
|
||||
z[j] = c;
|
||||
}
|
||||
z[j] = 0;
|
||||
if( j<i ) z[j] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2144,6 +2144,19 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){
|
||||
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.
|
||||
@@ -2242,8 +2255,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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
|
||||
@@ -2253,11 +2271,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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);
|
||||
@@ -2276,11 +2299,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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;
|
||||
@@ -2325,12 +2353,22 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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 ){
|
||||
@@ -2338,7 +2376,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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) {
|
||||
@@ -2373,19 +2411,20 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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]);
|
||||
}else
|
||||
|
||||
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
|
||||
fprintf(stderr,"%s",zHelp);
|
||||
if( HAS_TIMER ){
|
||||
fprintf(stderr,"%s",zTimerHelp);
|
||||
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=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
|
||||
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
|
||||
fprintf(p->out, "%s", zHelp);
|
||||
}else
|
||||
|
||||
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 */
|
||||
@@ -2398,6 +2437,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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);
|
||||
@@ -2536,7 +2579,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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);
|
||||
@@ -2553,7 +2596,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
"ORDER BY 1",
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
}else{
|
||||
}else if( nArg==2 ){
|
||||
zShellStatic = azArg[1];
|
||||
rc = sqlite3_exec(p->db,
|
||||
"SELECT name FROM sqlite_master "
|
||||
@@ -2565,6 +2608,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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);
|
||||
@@ -2600,9 +2647,14 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
#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);
|
||||
@@ -2615,38 +2667,41 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}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");
|
||||
@@ -2654,23 +2709,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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;
|
||||
@@ -2691,32 +2739,45 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
|
||||
if( p->outfile[0]=='|' ){
|
||||
pclose(p->out);
|
||||
}else{
|
||||
output_file_close(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;
|
||||
}
|
||||
p->outfile[0] = 0;
|
||||
if( azArg[1][0]=='|' ){
|
||||
p->out = popen(&azArg[1][1], "w");
|
||||
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{
|
||||
p->outCount = 0;
|
||||
}
|
||||
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
|
||||
@@ -2730,7 +2791,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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);
|
||||
}
|
||||
@@ -2739,12 +2800,18 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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;
|
||||
@@ -2754,7 +2821,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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;
|
||||
@@ -2764,9 +2831,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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 ){
|
||||
@@ -2801,14 +2872,14 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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 ){
|
||||
@@ -2852,7 +2923,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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"
|
||||
@@ -2862,6 +2933,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
"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);
|
||||
@@ -2891,24 +2966,33 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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\"",
|
||||
@@ -2918,8 +3002,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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");
|
||||
@@ -2941,11 +3030,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
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;
|
||||
@@ -3151,20 +3245,32 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}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 ){
|
||||
@@ -3195,11 +3301,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
#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++){
|
||||
@@ -3213,6 +3319,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
meta_command_exit:
|
||||
if( p->outCount ){
|
||||
p->outCount--;
|
||||
if( p->outCount==0 ) output_reset(p);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3380,6 +3491,10 @@ static int process_input(struct callback_data *p, FILE *in){
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user