]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Bring CVS output into more commonly accepted practice. Tickets #2030, #1573.
authordrh <drh@noemail.net>
Thu, 26 Oct 2006 18:15:42 +0000 (18:15 +0000)
committerdrh <drh@noemail.net>
Thu, 26 Oct 2006 18:15:42 +0000 (18:15 +0000)
Add command-line options -bail and ".bail" commands.  Default behavior is
to continue after encountering an error.  Ticket #2045. (CVS 3491)

FossilOrigin-Name: 517712d6fbc5ba5299942a54852298030f4d3381

manifest
manifest.uuid
src/shell.c

index 291b03701ff019213b2b23bfbb5414f42584c636..5535fbce0257e969668f26040e7b950cb4f00b31 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Command-line\sshell\senhancements.\s\sBail\sout\swhen\serrors\sare\sseen\sin\nnon-interactive\smode.\s\sOverride\sisatty()\susing\s-interactive\sor\s-batch\ncommand-line\soptions.\s\sReport\sline\snumber\sin\serror\smessages.\nTickets\s#2009,\s#2045.\s(CVS\s3490)
-D 2006-10-26T14:25:58
+C Bring\sCVS\soutput\sinto\smore\scommonly\saccepted\spractice.\s\sTickets\s#2030,\s#1573.\nAdd\scommand-line\soptions\s-bail\sand\s".bail"\scommands.\s\sDefault\sbehavior\sis\nto\scontinue\safter\sencountering\san\serror.\s\sTicket\s#2045.\s(CVS\s3491)
+D 2006-10-26T18:15:42
 F Makefile.in 4379c909d46b38b8c5db3533084601621d4f14b2
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -94,7 +94,7 @@ F src/printf.c b179b6ed12f793e028dd169e2e2e2b2a37eedc63
 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
 F src/select.c 6ba6d8ead43d0575ce1f8b418cc039f8f301389a
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
-F src/shell.c 73cbdcb3cdc63bca7630dc1dfe41ab9ac90d98db
+F src/shell.c 718c9dc51fd79b1a69c1c50c7fb750b522826e03
 F src/sqlite.h.in bf935004029631fd93d119bcf2f7259b9cb9ad5e
 F src/sqlite3ext.h 2c2156cc32a158e2b7bd9042d42accf94bff2e40
 F src/sqliteInt.h 637ef229c3d8e0f98096ab31c496efdf5361d678
@@ -419,7 +419,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P cde383eb467de0d752e94a22cd2f890c2dc599cc
-R 91d1f3065e90bb2f41c9cbd193a3305f
+P 3baa04cfb91039e27f642f6f78ef761b5770cb08
+R 5125f3c39d1102ce299e6d679578cc74
 U drh
-Z 74126c296022fab53cfd540120f95a5c
+Z e8dda10bb6ff8231cd4d006a2fdac63a
index 6d04ae75845871a4be07919d2c0723097f493e18..7176466aac70cb97c60f6684875d06ab8d7b9a2c 100644 (file)
@@ -1 +1 @@
-3baa04cfb91039e27f642f6f78ef761b5770cb08
\ No newline at end of file
+517712d6fbc5ba5299942a54852298030f4d3381
\ No newline at end of file
index 747100a8f1003caa847d4a363a0b14d9ea4ffe22..4860a250f5f8db95ff17bc9af87f5ea2e7868b27 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains code to implement the "sqlite" command line
 ** utility for accessing SQLite databases.
 **
-** $Id: shell.c,v 1.151 2006/10/26 14:25:58 drh Exp $
+** $Id: shell.c,v 1.152 2006/10/26 18:15:42 drh Exp $
 */
 #include <stdlib.h>
 #include <string.h>
 extern int isatty();
 #endif
 
+/*
+** If the following flag is set, then command execution stops
+** at an error if we are not interactive.
+*/
+static int bail_on_error = 0;
+
 /*
 ** Threat stdin as an interactive input if the following variable
 ** is true.  Otherwise, assume stdin is connected to a file or pipe.
@@ -353,6 +359,29 @@ static void output_html_string(FILE *out, const char *z){
   }
 }
 
+/*
+** If a field contains any character identified by a 1 in the following
+** array, then the string must be quoted for CSV.
+*/
+static const char needCsvQuote[] = {
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1, 
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
+};
+
 /*
 ** Output a single term of CSV.  Actually, p->separator is used for
 ** the separator, which may or may not be a comma.  p->nullvalue is
@@ -360,12 +389,27 @@ static void output_html_string(FILE *out, const char *z){
 ** appear outside of quotes.
 */
 static void output_csv(struct callback_data *p, const char *z, int bSep){
+  FILE *out = p->out;
   if( z==0 ){
-    fprintf(p->out,"%s",p->nullvalue);
-  }else if( isNumber(z, 0) ){
-    fprintf(p->out,"%s",z);
+    fprintf(out,"%s",p->nullvalue);
   }else{
-    output_c_string(p->out, z);
+    int i;
+    for(i=0; z[i]; i++){
+      if( needCsvQuote[((unsigned char*)z)[i]] ){
+        i = 0;
+        break;
+      }
+    }
+    if( i==0 ){
+      putc('"', out);
+      for(i=0; z[i]; i++){
+        if( z[i]=='"' ) putc('"', out);
+        putc(z[i], out);
+      }
+      putc('"', out);
+    }else{
+      fprintf(out, "%s", z);
+    }
   }
   if( bSep ){
     fprintf(p->out, p->separator);
@@ -912,6 +956,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
   if( nArg==0 ) return rc;
   n = strlen(azArg[0]);
   c = azArg[0][0];
+  if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
+    bail_on_error = booleanValue(azArg[1]);
+  }else
+
   if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
     struct callback_data data;
     char *zErrMsg = 0;
@@ -1476,24 +1524,30 @@ static int process_input(struct callback_data *p, FILE *in){
   char *zSql = 0;
   int nSql = 0;
   char *zErrMsg;
-  int rc = 0;
+  int rc;
+  int errCnt = 0;
   int lineno = 0;
   int startline = 0;
-  while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
+
+  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
+    fflush(p->out);
+    zLine = one_input_line(zSql, in);
+    if( zLine==0 ){
+      break;  /* We have reached EOF */
+    }
     if( seenInterrupt ){
       if( in!=0 ) break;
       seenInterrupt = 0;
     }
-    if( rc && (in!=0 || !stdin_is_interactive) ){
-      break;
-    }
     lineno++;
     if( p->echoOn ) printf("%s\n", zLine);
     if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
     if( zLine && zLine[0]=='.' && nSql==0 ){
-      int rc = do_meta_command(zLine, p);
+      rc = do_meta_command(zLine, p);
       free(zLine);
-      if( rc ) break;
+      if( rc ){
+        errCnt++;
+      }
       continue;
     }
     if( _is_command_terminator(zLine) ){
@@ -1542,6 +1596,7 @@ static int process_input(struct callback_data *p, FILE *in){
         }else{
           printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
         }
+        errCnt++;
       }
       free(zSql);
       zSql = 0;
@@ -1552,7 +1607,7 @@ static int process_input(struct callback_data *p, FILE *in){
     if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
     free(zSql);
   }
-  return rc;
+  return errCnt;
 }
 
 /*
@@ -1660,7 +1715,11 @@ static const char zOptions[] =
   "   -init filename       read/process named file\n"
   "   -echo                print commands before execution\n"
   "   -[no]header          turn headers on or off\n"
+  "   -bail                stop after hitting an error\n"
+  "   -interactive         force interactive I/O\n"
+  "   -batch               force batch I/O\n"
   "   -column              set output mode to 'column'\n"
+  "   -csv                 set output mode to 'csv'\n"
   "   -html                set output mode to HTML\n"
   "   -line                set output mode to 'line'\n"
   "   -list                set output mode to 'list'\n"
@@ -1786,6 +1845,9 @@ int main(int argc, char **argv){
       data.mode = MODE_Line;
     }else if( strcmp(z,"-column")==0 ){
       data.mode = MODE_Column;
+    }else if( strcmp(z,"-csv")==0 ){
+      data.mode = MODE_Csv;
+      strcpy(data.separator,",");
     }else if( strcmp(z,"-separator")==0 ){
       i++;
       sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
@@ -1798,6 +1860,8 @@ int main(int argc, char **argv){
       data.showHeader = 0;
     }else if( strcmp(z,"-echo")==0 ){
       data.echoOn = 1;
+    }else if( strcmp(z,"-bail")==0 ){
+      bail_on_error = 1;
     }else if( strcmp(z,"-version")==0 ){
       printf("%s\n", sqlite3_libversion());
       return 0;