From 636bf9f768347efec1342d45244719981df03fcf Mon Sep 17 00:00:00 2001 From: mistachkin Date: Sat, 19 Jul 2014 20:15:16 +0000 Subject: [PATCH 1/9] Add new ASCII mode to the shell capable of importing and exporting using the official unit and record separators (i.e. 0x1F and 0x1E, respectively). FossilOrigin-Name: 7fe601ead0d0ae26cb09d0dbc7d6367785376567 --- manifest | 21 +-- manifest.uuid | 2 +- src/shell.c | 344 +++++++++++++++++++++++++++++++++-------------- test/shell1.test | 46 +++++-- test/shell5.test | 39 +++++- 5 files changed, 328 insertions(+), 124 deletions(-) diff --git a/manifest b/manifest index 9c16ebe0d5..2bcc380e41 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\ssqlite3_stmt_busy()\sfunction\sso\sthat\sit\scorrectly\sreturns\strue\sfor\s"ROLLBACK"\sstatements\sthat\shave\sbeen\sstepped\sbut\snot\syet\sreset. -D 2014-07-19T17:57:10.785 +C Add\snew\sASCII\smode\sto\sthe\sshell\scapable\sof\simporting\sand\sexporting\susing\sthe\sofficial\sunit\sand\srecord\sseparators\s(i.e.\s0x1F\sand\s0x1E,\srespectively). +D 2014-07-19T20:15:16.631 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 6762c62e11b504aa014edceab8886495165e3a77 -F src/shell.c 566aee8213372a2e81ba0eb34e9759f7b2574009 +F src/shell.c f1524cdcf12af7eeff98c7846518ce5424d38d60 F src/sqlite.h.in fd8e3a36b0aded082dc93a4b89c1e85324b4cf75 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -818,11 +818,11 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21 F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test fb080d67c81e8a80a79ea04b36f127209b5bd112 +F test/shell1.test 4e4f8e6be18384f0bde93acc01947d7217e81774 F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5 -F test/shell5.test ef0c52952a4a96dc1d9ec3b1fa81ec897ca48154 +F test/shell5.test 3c9264ddf171d778d7d93bda5eea0bafe8a65069 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 @@ -1182,7 +1182,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 574cc8eb1448cff67390f2e16cc9b7c3ddd4658b -R 3e17c7c287ebc0f7c8d4dc519939fd8f -U dan -Z 2190a4b1d8dc0a3facc078eb683578eb +P 61cee3c0678f5abd9131a29ab946a5e71f55643e +R 2620c0e44150895c6e6dda7db94cda7b +T *branch * asciiMode +T *sym-asciiMode * +T -sym-trunk * +U mistachkin +Z 0122ab3028becc4213d4d02208439f07 diff --git a/manifest.uuid b/manifest.uuid index 5e45c34d1e..7ba436b017 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61cee3c0678f5abd9131a29ab946a5e71f55643e \ No newline at end of file +7fe601ead0d0ae26cb09d0dbc7d6367785376567 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 97167dc877..bae22d56a6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -457,7 +457,8 @@ struct callback_data { int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ char *zDestTable; /* Name of destination table when MODE_Insert */ - char separator[20]; /* Separator character for MODE_List */ + char colSeparator[20]; /* Column separator character for several modes */ + char rowSeparator[20]; /* Row separator character for MODE_Ascii */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ char nullvalue[20]; /* The text to print when a NULL comes back from @@ -488,6 +489,7 @@ struct callback_data { #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ #define MODE_Csv 7 /* Quote strings, numbers are plain */ #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ +#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ static const char *modeDescr[] = { "line", @@ -499,8 +501,16 @@ static const char *modeDescr[] = { "tcl", "csv", "explain", + "ascii", }; +/* +** These are the column/row separators used by the ASCII mode. +*/ +#define SEP_Line "\n" +#define SEP_Column "\x1F" +#define SEP_Row "\x1E" + /* ** Number of elements in an array */ @@ -667,11 +677,11 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){ fprintf(out,"%s",p->nullvalue); }else{ int i; - int nSep = strlen30(p->separator); + int nSep = strlen30(p->colSeparator); for(i=0; z[i]; i++){ if( needCsvQuote[((unsigned char*)z)[i]] - || (z[i]==p->separator[0] && - (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ + || (z[i]==p->colSeparator[0] && + (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ i = 0; break; } @@ -688,7 +698,7 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){ } } if( bSep ){ - fprintf(p->out, "%s", p->separator); + fprintf(p->out, "%s", p->colSeparator); } } @@ -720,10 +730,10 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int int len = strlen30(azCol[i] ? azCol[i] : ""); if( len>w ) w = len; } - if( p->cnt++>0 ) fprintf(p->out,"\n"); + if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator); for(i=0; iout,"%*s = %s\n", w, azCol[i], - azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out,"%*s = %s%s", w, azCol[i], + azArg[i] ? azArg[i] : p->nullvalue, p->rowSeparator); } break; } @@ -748,9 +758,11 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int } if( p->showHeader ){ if( w<0 ){ - fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": " "); + fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], + i==nArg-1 ? p->rowSeparator : " "); }else{ - fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], + i==nArg-1 ? p->rowSeparator : " "); } } } @@ -765,7 +777,7 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int } fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" "----------------------------------------------------------", - i==nArg-1 ? "\n": " "); + i==nArg-1 ? p->rowSeparator : " "); } } } @@ -788,10 +800,12 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int } if( w<0 ){ fprintf(p->out,"%*.*s%s",-w,-w, - azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); + azArg[i] ? azArg[i] : p->nullvalue, + i==nArg-1 ? p->rowSeparator : " "); }else{ fprintf(p->out,"%-*.*s%s",w,w, - azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); + azArg[i] ? azArg[i] : p->nullvalue, + i==nArg-1 ? p->rowSeparator : " "); } } break; @@ -800,7 +814,8 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int case MODE_List: { if( p->cnt++==0 && p->showHeader ){ for(i=0; iout,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); + fprintf(p->out,"%s%s",azCol[i], + i==nArg-1 ? p->rowSeparator : p->colSeparator); } } if( azArg==0 ) break; @@ -809,11 +824,11 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int if( z==0 ) z = p->nullvalue; fprintf(p->out, "%s", z); if( iout, "%s", p->separator); + fprintf(p->out, "%s", p->colSeparator); }else if( p->mode==MODE_Semi ){ - fprintf(p->out, ";\n"); + fprintf(p->out, ";%s", p->rowSeparator); }else{ - fprintf(p->out, "\n"); + fprintf(p->out, "%s", p->rowSeparator); } } break; @@ -842,16 +857,16 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int if( p->cnt++==0 && p->showHeader ){ for(i=0; iout,azCol[i] ? azCol[i] : ""); - if(iout, "%s", p->separator); + if(iout, "%s", p->colSeparator); } - fprintf(p->out,"\n"); + fprintf(p->out, "%s", p->rowSeparator); } if( azArg==0 ) break; for(i=0; iout, azArg[i] ? azArg[i] : p->nullvalue); - if(iout, "%s", p->separator); + if(iout, "%s", p->colSeparator); } - fprintf(p->out,"\n"); + fprintf(p->out, "%s", p->rowSeparator); break; } case MODE_Csv: { @@ -859,13 +874,13 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int for(i=0; iout,"\n"); + fprintf(p->out, "%s", p->rowSeparator); } if( azArg==0 ) break; for(i=0; iout,"\n"); + fprintf(p->out, "%s", p->rowSeparator); break; } case MODE_Insert: { @@ -897,6 +912,22 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int fprintf(p->out,");\n"); break; } + case MODE_Ascii: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i0 ) fprintf(p->out, "%s", p->colSeparator); + fprintf(p->out,"%s",azCol[i] ? azCol[i] : ""); + } + fprintf(p->out, "%s", p->rowSeparator); + } + if( azArg==0 ) break; + for(i=0; i0 ) fprintf(p->out, "%s", p->colSeparator); + fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullvalue); + } + fprintf(p->out, "%s", p->rowSeparator); + break; + } } return 0; } @@ -1574,6 +1605,7 @@ static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" + ".colseparator STRING This is an alias for .separator\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" @@ -1598,6 +1630,7 @@ static char zHelp[] = #endif ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" + " ascii Columns/rows delimited with 0x1F and 0x1E\n" " csv Comma-separated values\n" " column Left-aligned columns. (See .width)\n" " html HTML code\n" @@ -1615,11 +1648,12 @@ static char zHelp[] = ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" + ".rowseparator STRING Change row separator for output mode and .import\n" ".save FILE Write in-memory database into FILE\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" - ".separator STRING Change separator used by output mode and .import\n" + ".separator STRING Change column separator for 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" @@ -1832,10 +1866,10 @@ static void test_breakpoint(void){ } /* -** An object used to read a CSV file +** An object used to read a CSV and other files for import. */ -typedef struct CSVReader CSVReader; -struct CSVReader { +typedef struct ImportCtx ImportCtx; +struct ImportCtx { const char *zFile; /* Name of the input file */ FILE *in; /* Read the CSV text from this input stream */ char *z; /* Accumulated text for a field */ @@ -1843,11 +1877,12 @@ struct CSVReader { int nAlloc; /* Space allocated for z[] */ int nLine; /* Current line number */ int cTerm; /* Character that terminated the most recent field */ - int cSeparator; /* The separator character. (Usually ",") */ + int cColSep; /* The column separator character. (Usually ",") */ + int cRowSep; /* The row separator character. (Usually "\n") */ }; /* Append a single byte to z[] */ -static void csv_append_char(CSVReader *p, int c){ +static void import_append_char(ImportCtx *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; p->z = sqlite3_realloc(p->z, p->nAlloc); @@ -1865,15 +1900,17 @@ static void csv_append_char(CSVReader *p, int c){ ** + Input comes from p->in. ** + Store results in p->z of length p->n. Space to hold p->z comes ** from sqlite3_malloc(). -** + Use p->cSep as the separator. The default is ",". +** + Use p->cSep as the column separator. The default is ",". +** + Use p->rSep as the row separator. The default is "\n". ** + Keep track of the line number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ -static char *csv_read_one_field(CSVReader *p){ - int c, pc, ppc; - int cSep = p->cSeparator; +static char *csv_read_one_field(ImportCtx *p){ + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; p->n = 0; c = fgetc(p->in); if( c==EOF || seenInterrupt ){ @@ -1881,12 +1918,13 @@ static char *csv_read_one_field(CSVReader *p){ return 0; } if( c=='"' ){ + int pc, ppc; int startLine = p->nLine; int cQuote = c; pc = ppc = 0; while( 1 ){ c = fgetc(p->in); - if( c=='\n' ) p->nLine++; + if( c==rSep ) p->nLine++; if( c==cQuote ){ if( pc==cQuote ){ pc = 0; @@ -1894,8 +1932,8 @@ static char *csv_read_one_field(CSVReader *p){ } } if( (c==cSep && pc==cQuote) - || (c=='\n' && pc==cQuote) - || (c=='\n' && pc=='\r' && ppc==cQuote) + || (c==rSep && pc==cQuote) + || (c==rSep && pc=='\r' && ppc==cQuote) || (c==EOF && pc==cQuote) ){ do{ p->n--; }while( p->z[p->n]!=cQuote ); @@ -1909,19 +1947,19 @@ static char *csv_read_one_field(CSVReader *p){ if( c==EOF ){ fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", p->zFile, startLine, cQuote); - p->cTerm = EOF; + p->cTerm = c; break; } - csv_append_char(p, c); + import_append_char(p, c); ppc = pc; pc = c; } }else{ - while( c!=EOF && c!=cSep && c!='\n' ){ - csv_append_char(p, c); + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); c = fgetc(p->in); } - if( c=='\n' ){ + if( c==rSep ){ p->nLine++; if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; } @@ -1931,6 +1969,40 @@ static char *csv_read_one_field(CSVReader *p){ return p->z; } +/* Read a single field of ASCII delimited text. +** +** + Input comes from p->in. +** + Store results in p->z of length p->n. Space to hold p->z comes +** from sqlite3_malloc(). +** + Use p->cSep as the column separator. The default is "\x1F". +** + Use p->rSep as the row separator. The default is "\x1E". +** + Keep track of the row number in p->nLine. +** + Store the character that terminates the field in p->cTerm. Store +** EOF on end-of-file. +** + Report syntax errors on stderr +*/ +static char *ascii_read_one_field(ImportCtx *p){ + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); + c = fgetc(p->in); + } + if( c==rSep ){ + p->nLine++; + } + p->cTerm = c; + if( p->z ) p->z[p->n] = 0; + return p->z; +} + /* ** Try to transfer data for table zTable. If an error is seen while ** moving forward, try to go backwards. The backwards movement won't @@ -2485,9 +2557,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int needCommit; /* True to COMMIT or ROLLBACK at end */ - int nSep; /* Number of bytes in p->separator[] */ + int nSep; /* Number of bytes in p->colSeparator[] */ char *zSql; /* An SQL statement */ - CSVReader sCsv; /* Reader context */ + ImportCtx sCtx; /* Reader context */ + char *(*xRead)(ImportCtx*); /* Procecure to read one value */ int (*xCloser)(FILE*); /* Procedure to close th3 connection */ if( nArg!=3 ){ @@ -2497,55 +2570,71 @@ static int do_meta_command(char *zLine, struct callback_data *p){ zFile = azArg[1]; zTable = azArg[2]; seenInterrupt = 0; - memset(&sCsv, 0, sizeof(sCsv)); + memset(&sCtx, 0, sizeof(sCtx)); open_db(p, 0); - nSep = strlen30(p->separator); + nSep = strlen30(p->colSeparator); if( nSep==0 ){ - fprintf(stderr, "Error: non-null separator required for import\n"); + fprintf(stderr, "Error: non-null column separator required for import\n"); return 1; } if( nSep>1 ){ - fprintf(stderr, "Error: multi-character separators not allowed" + fprintf(stderr, "Error: multi-character column separators not allowed" " for import\n"); return 1; } - sCsv.zFile = zFile; - sCsv.nLine = 1; - if( sCsv.zFile[0]=='|' ){ - sCsv.in = popen(sCsv.zFile+1, "r"); - sCsv.zFile = ""; + nSep = strlen30(p->rowSeparator); + if( nSep==0 ){ + fprintf(stderr, "Error: non-null row separator required for import\n"); + return 1; + } + if( nSep>1 ){ + fprintf(stderr, "Error: multi-character row separators not allowed" + " for import\n"); + return 1; + } + sCtx.zFile = zFile; + sCtx.nLine = 1; + if( sCtx.zFile[0]=='|' ){ + sCtx.in = popen(sCtx.zFile+1, "r"); + sCtx.zFile = ""; xCloser = pclose; }else{ - sCsv.in = fopen(sCsv.zFile, "rb"); + sCtx.in = fopen(sCtx.zFile, "rb"); xCloser = fclose; } - if( sCsv.in==0 ){ + if( p->mode==MODE_Ascii ){ + xRead = ascii_read_one_field; + }else{ + xRead = csv_read_one_field; + } + if( sCtx.in==0 ){ fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); return 1; } - sCsv.cSeparator = p->separator[0]; + sCtx.cColSep = p->colSeparator[0]; + sCtx.cRowSep = p->rowSeparator[0]; zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); - xCloser(sCsv.in); + xCloser(sCtx.in); return 1; } nByte = strlen30(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */ + import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; - while( csv_read_one_field(&sCsv) ){ - zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z); + while( xRead(&sCtx) ){ + zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCtx.z); cSep = ','; - if( sCsv.cTerm!=sCsv.cSeparator ) break; + if( sCtx.cTerm!=sCtx.cColSep ) break; } if( cSep=='(' ){ sqlite3_free(zCreate); - sqlite3_free(sCsv.z); - xCloser(sCsv.in); - fprintf(stderr,"%s: empty file\n", sCsv.zFile); + sqlite3_free(sCtx.z); + xCloser(sCtx.in); + fprintf(stderr,"%s: empty file\n", sCtx.zFile); return 1; } zCreate = sqlite3_mprintf("%z\n)", zCreate); @@ -2554,8 +2643,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( rc ){ fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, sqlite3_errmsg(db)); - sqlite3_free(sCsv.z); - xCloser(sCsv.in); + sqlite3_free(sCtx.z); + xCloser(sCtx.in); return 1; } rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); @@ -2564,7 +2653,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( rc ){ if (pStmt) sqlite3_finalize(pStmt); fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); - xCloser(sCsv.in); + xCloser(sCtx.in); return 1; } nCol = sqlite3_column_count(pStmt); @@ -2574,7 +2663,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); - xCloser(sCsv.in); + xCloser(sCtx.in); return 1; } sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); @@ -2590,46 +2679,56 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); if (pStmt) sqlite3_finalize(pStmt); - xCloser(sCsv.in); + xCloser(sCtx.in); return 1; } needCommit = sqlite3_get_autocommit(db); if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0); do{ - int startLine = sCsv.nLine; + int startLine = sCtx.nLine; for(i=0; imode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); - if( i=nCol ){ sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); if( rc!=SQLITE_OK ){ - fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine, + fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine, sqlite3_errmsg(db)); } } - }while( sCsv.cTerm!=EOF ); + }while( sCtx.cTerm!=EOF ); - xCloser(sCsv.in); - sqlite3_free(sCsv.z); + xCloser(sCtx.in); + sqlite3_free(sCtx.z); sqlite3_finalize(pStmt); if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); }else @@ -2747,19 +2846,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){ p->mode = MODE_Html; }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ p->mode = MODE_Tcl; - sqlite3_snprintf(sizeof(p->separator), p->separator, " "); + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, " "); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line); }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; - sqlite3_snprintf(sizeof(p->separator), p->separator, ","); + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, ","); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line); }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; - sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, "\t"); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line); }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ p->mode = MODE_Insert; set_table_name(p, nArg>=3 ? azArg[2] : "table"); + }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ + p->mode = MODE_Ascii; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else { fprintf(stderr,"Error: mode should be one of: " - "column csv html insert line list tabs tcl\n"); + "ascii column csv html insert line list tabs tcl\n"); rc = 1; } }else @@ -3028,10 +3134,30 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else #endif + if( c=='r' && strncmp(azArg[0], "rowseparator", n)==0 ){ + if( nArg==2 ){ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, + "%.*s", (int)sizeof(p->rowSeparator)-1, azArg[1]); + }else{ + fprintf(stderr, "Usage: .rowseparator STRING\n"); + rc = 1; + } + }else + + if( c=='c' && strncmp(azArg[0], "colseparator", n)==0 ){ + if( nArg==2 ){ + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, + "%.*s", (int)sizeof(p->colSeparator)-1, azArg[1]); + }else{ + fprintf(stderr, "Usage: .colseparator STRING\n"); + rc = 1; + } + }else + 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]); + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, + "%.*s", (int)sizeof(p->colSeparator)-1, azArg[1]); }else{ fprintf(stderr, "Usage: .separator STRING\n"); rc = 1; @@ -3064,21 +3190,24 @@ static int do_meta_command(char *zLine, struct callback_data *p){ 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,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); - fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); - fprintf(p->out,"%9.9s: ", "nullvalue"); + fprintf(p->out,"%12.12s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off"); + fprintf(p->out,"%12.12s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); + fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); + fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]); + fprintf(p->out,"%12.12s: ", "nullvalue"); output_c_string(p->out, p->nullvalue); fprintf(p->out, "\n"); - fprintf(p->out,"%9.9s: %s\n","output", + fprintf(p->out,"%12.12s: %s\n","output", strlen30(p->outfile) ? p->outfile : "stdout"); - fprintf(p->out,"%9.9s: ", "separator"); - output_c_string(p->out, p->separator); + fprintf(p->out,"%12.12s: ", "colseparator"); + output_c_string(p->out, p->colSeparator); fprintf(p->out, "\n"); - fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off"); - fprintf(p->out,"%9.9s: ","width"); + fprintf(p->out,"%12.12s: ", "rowseparator"); + output_c_string(p->out, p->rowSeparator); + fprintf(p->out, "\n"); + fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off"); + fprintf(p->out,"%12.12s: ","width"); for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { fprintf(p->out,"%d ",p->colWidth[i]); } @@ -3672,8 +3801,10 @@ static int process_sqliterc( ** Show available command line options */ static const char zOptions[] = + " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" + " -colseparator SEP same as -separator\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" @@ -3693,6 +3824,7 @@ static const char zOptions[] = " -multiplex enable the multiplexor VFS\n" #endif " -nullvalue TEXT set text string for NULL values. Default ''\n" + " -rowseparator SEP set output line separator. Default: '\\n'\n" " -separator SEP set output field separator. Default: '|'\n" " -stats print memory stats before each finalize\n" " -version show SQLite version\n" @@ -3720,7 +3852,8 @@ static void usage(int showDetail){ static void main_init(struct callback_data *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; - memcpy(data->separator,"|", 2); + memcpy(data->colSeparator,"|", 2); + memcpy(data->rowSeparator,"\n", 2); data->showHeader = 0; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); @@ -3918,9 +4051,18 @@ int main(int argc, char **argv){ data.mode = MODE_Column; }else if( strcmp(z,"-csv")==0 ){ data.mode = MODE_Csv; - memcpy(data.separator,",",2); - }else if( strcmp(z,"-separator")==0 ){ - sqlite3_snprintf(sizeof(data.separator), data.separator, + memcpy(data.colSeparator,",",2); + }else if( strcmp(z,"-ascii")==0 ){ + data.mode = MODE_Ascii; + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, + SEP_Column); + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, + SEP_Row); + }else if( strcmp(z,"-separator")==0 || strcmp(z,"-colseparator")==0 ){ + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, + "%s",cmdline_option_value(argc,argv,++i)); + }else if( strcmp(z,"-rowseparator")==0 ){ + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-nullvalue")==0 ){ sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, diff --git a/test/shell1.test b/test/shell1.test index e6fb0c28d2..9c7190e007 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -206,10 +206,10 @@ do_test shell1-2.2.4 { } {0 {}} do_test shell1-2.2.5 { catchcmd "test.db" ".mode \"insert FOO" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} do_test shell1-2.2.6 { catchcmd "test.db" ".mode \'insert FOO" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} # check multiple tokens, and quoted tokens do_test shell1-2.3.1 { @@ -237,7 +237,7 @@ do_test shell1-2.3.7 { # check quoted args are unquoted do_test shell1-2.4.1 { catchcmd "test.db" ".mode FOO" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} do_test shell1-2.4.2 { catchcmd "test.db" ".mode csv" } {0 {}} @@ -420,6 +420,7 @@ do_test shell1-3.12.3 { } {1 {Usage: .indices ?LIKE-PATTERN?}} # .mode MODE ?TABLE? Set output mode where MODE is one of: +# ascii Columns/rows delimited with 0x1F and 0x1E # csv Comma-separated values # column Left-aligned columns. (See .width) # html HTML
code @@ -430,10 +431,10 @@ do_test shell1-3.12.3 { # tcl TCL list elements do_test shell1-3.13.1 { catchcmd "test.db" ".mode" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii 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}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} do_test shell1-3.13.3 { catchcmd "test.db" ".mode csv" } {0 {}} @@ -466,10 +467,10 @@ do_test shell1-3.13.11 { # don't allow partial mode type matches do_test shell1-3.13.12 { catchcmd "test.db" ".mode l" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} do_test shell1-3.13.13 { catchcmd "test.db" ".mode li" -} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}} +} {1 {Error: mode should be one of: ascii column csv html insert line list tabs tcl}} do_test shell1-3.13.14 { catchcmd "test.db" ".mode lin" } {0 {}} @@ -585,7 +586,7 @@ CREATE VIEW v2 AS SELECT x+1 AS y FROM t1; CREATE VIEW v1 AS SELECT y+1 FROM v2;}} db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} -# .separator STRING Change separator used by output mode and .import +# .separator STRING Change column separator used by output and .import do_test shell1-3.22.1 { catchcmd "test.db" ".separator" } {1 {Usage: .separator STRING}} @@ -606,10 +607,11 @@ do_test shell1-3.23.1 { [regexp {mode:} $res] \ [regexp {nullvalue:} $res] \ [regexp {output:} $res] \ - [regexp {separator:} $res] \ + [regexp {colseparator:} $res] \ + [regexp {rowseparator:} $res] \ [regexp {stats:} $res] \ [regexp {width:} $res] -} {1 1 1 1 1 1 1 1 1} +} {1 1 1 1 1 1 1 1 1 1} do_test shell1-3.23.2 { # too many arguments catchcmd "test.db" ".show BAD" @@ -809,4 +811,28 @@ do_test shell1-4.6 { ";" "$"} 7} +# .colseparator STRING Change column separator used by output and .import +do_test shell1-5.1.1 { + catchcmd "test.db" ".colseparator" +} {1 {Usage: .colseparator STRING}} +do_test shell1-5.1.2 { + catchcmd "test.db" ".colseparator FOO" +} {0 {}} +do_test shell1-5.1.3 { + # too many arguments + catchcmd "test.db" ".colseparator FOO BAD" +} {1 {Usage: .colseparator STRING}} + +# .rowseparator STRING Change row separator used by output and .import +do_test shell1-6.1.1 { + catchcmd "test.db" ".rowseparator" +} {1 {Usage: .rowseparator STRING}} +do_test shell1-6.1.2 { + catchcmd "test.db" ".rowseparator FOO" +} {0 {}} +do_test shell1-6.1.3 { + # too many arguments + catchcmd "test.db" ".rowseparator FOO BAD" +} {1 {Usage: .rowseparator STRING}} + finish_test diff --git a/test/shell5.test b/test/shell5.test index 6e9dd20639..4e11e8798b 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -64,10 +64,16 @@ do_test shell5-1.2.3 { catchcmd "test.db" ".separator FOO BAD" } {1 {Usage: .separator STRING}} -# separator should default to "|" -do_test shell5-1.3.1 { +# column separator should default to "|" +do_test shell5-1.3.1.1 { set res [catchcmd "test.db" ".show"] - list [regexp {separator: \"\|\"} $res] + list [regexp {colseparator: \"\|\"} $res] +} {1} + +# row separator should default to "\n" +do_test shell5-1.3.1.2 { + set res [catchcmd "test.db" ".show"] + list [regexp {rowseparator: \"\\n\"} $res] } {1} # set separator to different value. @@ -369,5 +375,32 @@ CREATE TABLE t4(a, b); db eval { SELECT * FROM t4 } } {xy\" hello one 2 {} {}} +#---------------------------------------------------------------------------- +# Tests for the shell "ascii" import/export mode. +# +do_test shell5-3.1 { + set fd [open shell5.csv w] + fconfigure $fd -encoding binary -translation binary + puts -nonewline $fd "\"test 1\"\x1F,test 2\r\n\x1E" + puts -nonewline $fd "test 3\x1Ftest 4\n" + close $fd + catchcmd test.db { +.mode ascii +CREATE TABLE t5(a, b); +.import shell5.csv t5 + } + db eval { SELECT * FROM t5 } +} "\{\"test 1\"} \{,test 2\r\n\} \{test 3\} \{test 4\n\}" + +# +# NOTE: This test ends up converting the "\r\n" to "\n\n" due +# to end-of-line translation on the "stdout" channel. +# +do_test shell5-3.2 { + catchcmd test.db { +.mode ascii +SELECT * FROM t5; + } +} "0 \{\"test 1\"\x1F,test 2\n\n\x1Etest 3\x1Ftest 4\n\x1E\}" finish_test From 486fd43fd848bb5003127bbdf51370dc6b9a5faf Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 24 Jul 2014 22:20:23 +0000 Subject: [PATCH 2/9] Fix typo in comment and update help text. FossilOrigin-Name: 289092bb64463efe78a5f01b06b24aa664a31feb --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 7 ++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 0a878d2dde..3db2a79fc6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\supdates\sfrom\strunk. -D 2014-07-24T22:13:12.489 +C Fix\stypo\sin\scomment\sand\supdate\shelp\stext. +D 2014-07-24T22:20:23.336 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 6762c62e11b504aa014edceab8886495165e3a77 -F src/shell.c 3af679cad9c2e7caf7f8b997fb543afbc76d7c13 +F src/shell.c e1177e053e214be9c1549dac5bbcb2164b6114dd F src/sqlite.h.in ac4451c9da2771d2f4d702ef89722407242906d9 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1184,7 +1184,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7fe601ead0d0ae26cb09d0dbc7d6367785376567 fb1048cb2b613a0dbfe625a5df05e9dcd736a433 -R 551b1710cff332eae579e1d24ac340a5 +P 8dc0cdf652f099d464d3de416dffd83efb895009 +R df3c0e791329cbe951d92033daed226e U mistachkin -Z 5a827010d4d8351c000cbf9e79de9417 +Z b422ee17d0b3078b84860803513f7cb8 diff --git a/manifest.uuid b/manifest.uuid index 3cf998f636..27a93d5aad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8dc0cdf652f099d464d3de416dffd83efb895009 \ No newline at end of file +289092bb64463efe78a5f01b06b24aa664a31feb \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 55b41662ea..78339db8b4 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1623,7 +1623,8 @@ static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" - ".colseparator STRING This is an alias for .separator\n" + ".colseparator STRING This is an alias for the one argument version of\n" + " .separator\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" @@ -2646,7 +2647,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int nSep; /* Number of bytes in p->colSeparator[] */ char *zSql; /* An SQL statement */ ImportCtx sCtx; /* Reader context */ - char *(*xRead)(ImportCtx*); /* Procecure to read one value */ + char *(*xRead)(ImportCtx*); /* Procedure to read one value */ int (*xCloser)(FILE*); /* Procedure to close th3 connection */ if( nArg!=3 ){ @@ -3899,7 +3900,7 @@ static const char zOptions[] = " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" - " -colseparator SEP same as -separator\n" + " -colseparator SEP same as -separator with one argument\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" From 815ab5ac49d9d7c7510f54db5a58ae57e6da215e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 24 Jul 2014 22:33:47 +0000 Subject: [PATCH 3/9] Update a shell test case. FossilOrigin-Name: b84008cb964f234b6a6b441f738e344158c4c92a --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/shell1.test | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3db2a79fc6..9cce47d31d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sin\scomment\sand\supdate\shelp\stext. -D 2014-07-24T22:20:23.336 +C Update\sa\sshell\stest\scase. +D 2014-07-24T22:33:47.040 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -820,7 +820,7 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21 F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test d13ff516e3fcd4061bd072f56fd1551f2bf7fe52 +F test/shell1.test 1c0b7a79b1b91a56253ee0c4fbb309d39d16641e F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5 @@ -1184,7 +1184,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8dc0cdf652f099d464d3de416dffd83efb895009 -R df3c0e791329cbe951d92033daed226e +P 289092bb64463efe78a5f01b06b24aa664a31feb +R 2dda198fecf0d2cc936f765b01233dec U mistachkin -Z b422ee17d0b3078b84860803513f7cb8 +Z 05cc0be56c34ce76332247b4a337d27f diff --git a/manifest.uuid b/manifest.uuid index 27a93d5aad..eb0aaa3df5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -289092bb64463efe78a5f01b06b24aa664a31feb \ No newline at end of file +b84008cb964f234b6a6b441f738e344158c4c92a \ No newline at end of file diff --git a/test/shell1.test b/test/shell1.test index 0a0d0e3a16..efb45cdd95 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -612,9 +612,10 @@ do_test shell1-3.23.1 { [regexp {output:} $res] \ [regexp {colseparator:} $res] \ [regexp {rowseparator:} $res] \ + [regexp {newline:} $res] \ [regexp {stats:} $res] \ [regexp {width:} $res] -} {1 1 1 1 1 1 1 1 1 1} +} {1 1 1 1 1 1 1 1 1 1 1} do_test shell1-3.23.2 { # too many arguments catchcmd "test.db" ".show BAD" From 22c9638efdfd962bfe9e27909c1bcc08e034f5b8 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 24 Jul 2014 22:51:18 +0000 Subject: [PATCH 4/9] Correct help text and make consistent use of snprintf. FossilOrigin-Name: 9c424a5c50e4a2ed36556e99fba0e7072a2d3468 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 9cce47d31d..3c60bf2ba4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sa\sshell\stest\scase. -D 2014-07-24T22:33:47.040 +C Correct\shelp\stext\sand\smake\sconsistent\suse\sof\ssnprintf. +D 2014-07-24T22:51:18.860 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 6762c62e11b504aa014edceab8886495165e3a77 -F src/shell.c e1177e053e214be9c1549dac5bbcb2164b6114dd +F src/shell.c 5129214fbe720ce24802e750b1ac0a49f04034cd F src/sqlite.h.in ac4451c9da2771d2f4d702ef89722407242906d9 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1184,7 +1184,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 289092bb64463efe78a5f01b06b24aa664a31feb -R 2dda198fecf0d2cc936f765b01233dec +P b84008cb964f234b6a6b441f738e344158c4c92a +R 0b04208537b14ee3bcc223e1a9755bab U mistachkin -Z 05cc0be56c34ce76332247b4a337d27f +Z 0945ca559f52609ad97025a5011e881c diff --git a/manifest.uuid b/manifest.uuid index eb0aaa3df5..6c6478f98e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b84008cb964f234b6a6b441f738e344158c4c92a \ No newline at end of file +9c424a5c50e4a2ed36556e99fba0e7072a2d3468 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 78339db8b4..3f67986967 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3225,7 +3225,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='r' && strncmp(azArg[0], "rowseparator", n)==0 ){ if( nArg==2 ){ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, - "%.*s", (int)sizeof(p->rowSeparator)-1, azArg[1]); + "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[1]); }else{ fprintf(stderr, "Usage: .rowseparator STRING\n"); rc = 1; @@ -3235,7 +3235,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='c' && strncmp(azArg[0], "colseparator", n)==0 ){ if( nArg==2 ){ sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, - "%.*s", (int)sizeof(p->colSeparator)-1, azArg[1]); + "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); }else{ fprintf(stderr, "Usage: .colseparator STRING\n"); rc = 1; @@ -3249,11 +3249,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } if( nArg>=2 ){ sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, - "%.*s", (int)sizeof(p->colSeparator)-1, azArg[1]); + "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); } if( nArg>=3 ){ sqlite3_snprintf(sizeof(p->newline), p->newline, - "%.*s", (int)sizeof(p->newline)-1, azArg[2]); + "%.*s", (int)ArraySize(p->newline)-1, azArg[2]); } }else @@ -3900,7 +3900,7 @@ static const char zOptions[] = " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" - " -colseparator SEP same as -separator with one argument\n" + " -colseparator SEP same as -separator\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" From e0d6885f1760c50515876456a8fbb6fbfbb278fd Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Dec 2014 03:12:33 +0000 Subject: [PATCH 5/9] Simplify and cleanup the implementation of the new ASCII mode for the shell. FossilOrigin-Name: 66a28f7abaeaf1ebe6e43d856af88ac64b1ff230 --- manifest | 16 +++++------ manifest.uuid | 2 +- src/shell.c | 69 +++++++++++++++--------------------------------- test/shell1.test | 35 ++++-------------------- test/shell5.test | 4 +-- 5 files changed, 38 insertions(+), 88 deletions(-) diff --git a/manifest b/manifest index 82f498501b..2a02591071 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\supdates\sfrom\strunk. -D 2014-12-11T02:28:42.201 +C Simplify\sand\scleanup\sthe\simplementation\sof\sthe\snew\sASCII\smode\sfor\sthe\sshell. +D 2014-12-11T03:12:33.799 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 -F src/shell.c 1c7787d1066d1a858b8a4812663fde0e4a85b755 +F src/shell.c 84359f80c432f8b34f0af4fdee8055c9fc2639a2 F src/sqlite.h.in 2e699aabd1df6042aff4265cd93bdc8812629f11 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d @@ -851,11 +851,11 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 0d2cece602988da3fa066c00adf19cda0b1306ad +F test/shell1.test cdeb849acc2c37aada70d084564b0cc0a2c7df08 F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5 -F test/shell5.test 7dbc03751ceda1e5ce75553dff735a7ef0dea15c +F test/shell5.test d17a02d2327aadc6c062d5ba16b737d32601b11b F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 @@ -1227,7 +1227,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 51f33cf1290cf767c1c6ba0228f4f30e4059c994 d9f916ba09f1a61684b4d59548ab6cf71cdb6a37 -R 15ef4ed782851554150951631e8659fc +P 5b5d3e4d0d158594c0db05ddbf4d926b65825042 +R 7df644943b04f66f737e7f900957f44a U mistachkin -Z e24780e51cf083f098b96480beceaf1e +Z bc502efd9af4cfe5719e73721b9180f9 diff --git a/manifest.uuid b/manifest.uuid index 3eb6df633f..7be32cae90 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5b5d3e4d0d158594c0db05ddbf4d926b65825042 \ No newline at end of file +66a28f7abaeaf1ebe6e43d856af88ac64b1ff230 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 22e691a8cb..c1d8f18333 100644 --- a/src/shell.c +++ b/src/shell.c @@ -911,13 +911,13 @@ static int shell_callback( for(i=0; iout, "%s", p->newline); + fprintf(p->out, "%s", p->rowSeparator); } if( nArg>0 ){ for(i=0; iout, "%s", p->newline); + fprintf(p->out, "%s", p->rowSeparator); } #if defined(WIN32) || defined(_WIN32) fflush(p->out); @@ -1711,8 +1711,6 @@ static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" - ".colseparator STRING This is an alias for the one argument version of\n" - " .separator\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" @@ -1737,13 +1735,13 @@ static char zHelp[] = #endif ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" - " ascii Columns/rows delimited with 0x1F and 0x1E\n" + " ascii Columns/rows delimited by 0x1F and 0x1E\n" " csv Comma-separated values\n" " column Left-aligned columns. (See .width)\n" " html HTML
code\n" " insert SQL insert statements for TABLE\n" " line One value per line\n" - " list Values delimited by .separator string\n" + " list Values delimited by .separator strings\n" " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" @@ -1755,14 +1753,13 @@ static char zHelp[] = ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" - ".rowseparator STRING Change row separator for output mode and .import\n" ".save FILE Write in-memory database into FILE\n" ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" ".schema ?TABLE? Show the CREATE statements\n" " If TABLE specified, only show tables matching\n" " LIKE pattern TABLE.\n" - ".separator STRING ?NL? Change column separator for output mode and .import\n" - " NL is the end-of-line mark for CSV\n" + ".separator COL ?ROW? Change the column separator and optionally the row\n" + " separator for both the 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" @@ -2764,6 +2761,14 @@ static int do_meta_command(char *zLine, ShellState *p){ fprintf(stderr, "Error: non-null row separator required for import\n"); return 1; } + if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){ + /* When importing CSV (only), if the row separator is set to the + ** default output row separator, change it to the default input + ** row separator. This avoids having to maintain different input + ** and output row separators. */ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + nSep = strlen30(p->rowSeparator); + } if( nSep>1 ){ fprintf(stderr, "Error: multi-character row separators not allowed" " for import\n"); @@ -3027,9 +3032,8 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; - sqlite3_snprintf(sizeof(p->newline), p->newline, SEP_CrLf); sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); @@ -3334,29 +3338,9 @@ static int do_meta_command(char *zLine, ShellState *p){ }else #endif - if( c=='r' && strncmp(azArg[0], "rowseparator", n)==0 ){ - if( nArg==2 ){ - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, - "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[1]); - }else{ - fprintf(stderr, "Usage: .rowseparator STRING\n"); - rc = 1; - } - }else - - if( c=='c' && strncmp(azArg[0], "colseparator", n)==0 ){ - if( nArg==2 ){ - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, - "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); - }else{ - fprintf(stderr, "Usage: .colseparator STRING\n"); - rc = 1; - } - }else - if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ if( nArg<2 || nArg>3 ){ - fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n"); + fprintf(stderr, "Usage: .separator COL ?ROW?\n"); rc = 1; } if( nArg>=2 ){ @@ -3364,8 +3348,8 @@ static int do_meta_command(char *zLine, ShellState *p){ "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); } if( nArg>=3 ){ - sqlite3_snprintf(sizeof(p->newline), p->newline, - "%.*s", (int)ArraySize(p->newline)-1, azArg[2]); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, + "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); } }else @@ -3412,9 +3396,6 @@ static int do_meta_command(char *zLine, ShellState *p){ fprintf(p->out,"%12.12s: ", "rowseparator"); output_c_string(p->out, p->rowSeparator); fprintf(p->out, "\n"); - fprintf(p->out,"%12.12s: ", "newline"); - output_c_string(p->out, p->newline); - fprintf(p->out, "\n"); fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off"); fprintf(p->out,"%12.12s: ","width"); for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { @@ -4080,7 +4061,6 @@ static const char zOptions[] = " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" - " -colseparator SEP same as -separator\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" @@ -4100,12 +4080,11 @@ static const char zOptions[] = #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif - " -newline SEP set newline character(s) for CSV\n" + " -newline SEP set output row separator. Default: '\\n'\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" - " -rowseparator SEP set output line separator. Default: '\\n'\n" " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n" - " -separator SEP set output field separator. Default: '|'\n" + " -separator SEP set output column separator. Default: '|'\n" " -stats print memory stats before each finalize\n" " -version show SQLite version\n" " -vfs NAME use NAME as the default VFS\n" @@ -4134,7 +4113,6 @@ static void main_init(ShellState *data) { data->mode = MODE_List; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); - memcpy(data->newline,SEP_CrLf, 3); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; sqlite3_config(SQLITE_CONFIG_URI, 1); @@ -4380,14 +4358,11 @@ int main(int argc, char **argv){ SEP_Unit); sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record); - }else if( strcmp(z,"-separator")==0 || strcmp(z,"-colseparator")==0 ){ + }else if( strcmp(z,"-separator")==0 ){ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, "%s",cmdline_option_value(argc,argv,++i)); - }else if( strcmp(z,"-rowseparator")==0 ){ - sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, - "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-newline")==0 ){ - sqlite3_snprintf(sizeof(data.newline), data.newline, + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-nullvalue")==0 ){ sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, diff --git a/test/shell1.test b/test/shell1.test index c315d85c46..f24b00d494 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -421,13 +421,13 @@ do_test shell1-3.12.3 { } {1 {Usage: .indices ?LIKE-PATTERN?}} # .mode MODE ?TABLE? Set output mode where MODE is one of: -# ascii Columns/rows delimited with 0x1F and 0x1E +# ascii Columns/rows delimited by 0x1F and 0x1E # csv Comma-separated values # column Left-aligned columns. (See .width) # html HTML
code # insert SQL insert statements for TABLE # line One value per line -# list Values delimited by .separator string +# list Values delimited by .separator strings # tabs Tab-separated values # tcl TCL list elements do_test shell1-3.13.1 { @@ -590,7 +590,7 @@ db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} # .separator STRING Change column separator used by output and .import do_test shell1-3.22.1 { catchcmd "test.db" ".separator" -} {1 {Usage: .separator SEPARATOR ?NEWLINE?}} +} {1 {Usage: .separator COL ?ROW?}} do_test shell1-3.22.2 { catchcmd "test.db" ".separator FOO" } {0 {}} @@ -600,7 +600,7 @@ do_test shell1-3.22.3 { do_test shell1-3.22.4 { # too many arguments catchcmd "test.db" ".separator FOO BAD BAD2" -} {1 {Usage: .separator SEPARATOR ?NEWLINE?}} +} {1 {Usage: .separator COL ?ROW?}} # .show Show the current values for various settings do_test shell1-3.23.1 { @@ -613,10 +613,9 @@ do_test shell1-3.23.1 { [regexp {output:} $res] \ [regexp {colseparator:} $res] \ [regexp {rowseparator:} $res] \ - [regexp {newline:} $res] \ [regexp {stats:} $res] \ [regexp {width:} $res] -} {1 1 1 1 1 1 1 1 1 1 1} +} {1 1 1 1 1 1 1 1 1 1} do_test shell1-3.23.2 { # too many arguments catchcmd "test.db" ".show BAD" @@ -816,28 +815,4 @@ do_test shell1-4.6 { ";" "$"} 7} -# .colseparator STRING Change column separator used by output and .import -do_test shell1-5.1.1 { - catchcmd "test.db" ".colseparator" -} {1 {Usage: .colseparator STRING}} -do_test shell1-5.1.2 { - catchcmd "test.db" ".colseparator FOO" -} {0 {}} -do_test shell1-5.1.3 { - # too many arguments - catchcmd "test.db" ".colseparator FOO BAD" -} {1 {Usage: .colseparator STRING}} - -# .rowseparator STRING Change row separator used by output and .import -do_test shell1-6.1.1 { - catchcmd "test.db" ".rowseparator" -} {1 {Usage: .rowseparator STRING}} -do_test shell1-6.1.2 { - catchcmd "test.db" ".rowseparator FOO" -} {0 {}} -do_test shell1-6.1.3 { - # too many arguments - catchcmd "test.db" ".rowseparator FOO BAD" -} {1 {Usage: .rowseparator STRING}} - finish_test diff --git a/test/shell5.test b/test/shell5.test index 7c28d0bcd8..e384e375fb 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -55,7 +55,7 @@ do_test shell5-1.1.3 { # .separator STRING Change separator used by output mode and .import do_test shell5-1.2.1 { catchcmd "test.db" ".separator" -} {1 {Usage: .separator SEPARATOR ?NEWLINE?}} +} {1 {Usage: .separator COL ?ROW?}} do_test shell5-1.2.2 { catchcmd "test.db" ".separator ONE" } {0 {}} @@ -65,7 +65,7 @@ do_test shell5-1.2.3 { do_test shell5-1.2.4 { # too many arguments catchcmd "test.db" ".separator ONE TWO THREE" -} {1 {Usage: .separator SEPARATOR ?NEWLINE?}} +} {1 {Usage: .separator COL ?ROW?}} # column separator should default to "|" do_test shell5-1.3.1.1 { From f1f84a6ec1cffaaf7a78608deca8607b6dc942d6 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Dec 2014 03:20:58 +0000 Subject: [PATCH 6/9] Further simplify shell mode changes. FossilOrigin-Name: cf9c6e7eea4cab073e608e6fefdd24be87a8abeb --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2a02591071..498be7827e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sand\scleanup\sthe\simplementation\sof\sthe\snew\sASCII\smode\sfor\sthe\sshell. -D 2014-12-11T03:12:33.799 +C Further\ssimplify\sshell\smode\schanges. +D 2014-12-11T03:20:58.752 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 -F src/shell.c 84359f80c432f8b34f0af4fdee8055c9fc2639a2 +F src/shell.c 4649c6bdfcc72cebffa770f9a47d37b8a9120215 F src/sqlite.h.in 2e699aabd1df6042aff4265cd93bdc8812629f11 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d @@ -1227,7 +1227,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5b5d3e4d0d158594c0db05ddbf4d926b65825042 -R 7df644943b04f66f737e7f900957f44a +P 66a28f7abaeaf1ebe6e43d856af88ac64b1ff230 +R 96c15ebe6218f037cbb3aa3c87063a4c U mistachkin -Z bc502efd9af4cfe5719e73721b9180f9 +Z 166f8db90bdd2987f2d3879c9c0b3446 diff --git a/manifest.uuid b/manifest.uuid index 7be32cae90..edf02da4cf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66a28f7abaeaf1ebe6e43d856af88ac64b1ff230 \ No newline at end of file +cf9c6e7eea4cab073e608e6fefdd24be87a8abeb \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index c1d8f18333..a363d79bfa 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3029,7 +3029,6 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ p->mode = MODE_Tcl; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); @@ -3037,7 +3036,6 @@ static int do_meta_command(char *zLine, ShellState *p){ }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ p->mode = MODE_Insert; set_table_name(p, nArg>=3 ? azArg[2] : "table"); From 44ca92062543cdd7918f0ddfd7c5566cc656cf03 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Dec 2014 03:25:05 +0000 Subject: [PATCH 7/9] Remove an unused structure member. FossilOrigin-Name: d8404340cb01af440feebd19d291eb7198cfa576 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 498be7827e..c6c2741cf4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\ssimplify\sshell\smode\schanges. -D 2014-12-11T03:20:58.752 +C Remove\san\sunused\sstructure\smember. +D 2014-12-11T03:25:05.862 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 -F src/shell.c 4649c6bdfcc72cebffa770f9a47d37b8a9120215 +F src/shell.c d2c9565c39b74fbbafc5e298f46a5dce2712633a F src/sqlite.h.in 2e699aabd1df6042aff4265cd93bdc8812629f11 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d @@ -1227,7 +1227,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 66a28f7abaeaf1ebe6e43d856af88ac64b1ff230 -R 96c15ebe6218f037cbb3aa3c87063a4c +P cf9c6e7eea4cab073e608e6fefdd24be87a8abeb +R ddc1d3f4245eaeea9a8356078a1ff2c8 U mistachkin -Z 166f8db90bdd2987f2d3879c9c0b3446 +Z 68f03e9f12ac1359ea66745b2be1a192 diff --git a/manifest.uuid b/manifest.uuid index edf02da4cf..92c9024aaa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf9c6e7eea4cab073e608e6fefdd24be87a8abeb \ No newline at end of file +d8404340cb01af440feebd19d291eb7198cfa576 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index a363d79bfa..21073c90f3 100644 --- a/src/shell.c +++ b/src/shell.c @@ -473,7 +473,6 @@ struct ShellState { char *zDestTable; /* Name of destination table when MODE_Insert */ char colSeparator[20]; /* Column separator character for several modes */ char rowSeparator[20]; /* Row separator character for MODE_Ascii */ - char newline[20]; /* Record separator in MODE_Csv */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ char nullvalue[20]; /* The text to print when a NULL comes back from From 44b99f7e2ef1fa751ad556e4ed3b4c99ade98dfe Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Dec 2014 03:29:14 +0000 Subject: [PATCH 8/9] Rename a structure member to improve code clarity. FossilOrigin-Name: d48eda16ef8a84a93de9c6f38f794aceb4a6ba0d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 30 +++++++++++++++--------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index c6c2741cf4..8e4591a12c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\sstructure\smember. -D 2014-12-11T03:25:05.862 +C Rename\sa\sstructure\smember\sto\simprove\scode\sclarity. +D 2014-12-11T03:29:14.206 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 -F src/shell.c d2c9565c39b74fbbafc5e298f46a5dce2712633a +F src/shell.c 3628fab3fba6490bebba7fa63989c5c410eba0a5 F src/sqlite.h.in 2e699aabd1df6042aff4265cd93bdc8812629f11 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d @@ -1227,7 +1227,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P cf9c6e7eea4cab073e608e6fefdd24be87a8abeb -R ddc1d3f4245eaeea9a8356078a1ff2c8 +P d8404340cb01af440feebd19d291eb7198cfa576 +R 46f56278d908459d592a073dfada5d9c U mistachkin -Z 68f03e9f12ac1359ea66745b2be1a192 +Z d954c642e1623a1d799298570f596d90 diff --git a/manifest.uuid b/manifest.uuid index 92c9024aaa..28bc895227 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8404340cb01af440feebd19d291eb7198cfa576 \ No newline at end of file +d48eda16ef8a84a93de9c6f38f794aceb4a6ba0d \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 21073c90f3..d102d4c047 100644 --- a/src/shell.c +++ b/src/shell.c @@ -475,7 +475,7 @@ struct ShellState { char rowSeparator[20]; /* Row separator character for MODE_Ascii */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ - char nullvalue[20]; /* The text to print when a NULL comes back from + char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ @@ -693,14 +693,14 @@ static const char needCsvQuote[] = { /* ** 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 +** the separator, which may or may not be a comma. p->nullValue is ** the null value. Strings are quoted if necessary. The separator ** is only issued if bSep is true. */ static void output_csv(ShellState *p, const char *z, int bSep){ FILE *out = p->out; if( z==0 ){ - fprintf(out,"%s",p->nullvalue); + fprintf(out,"%s",p->nullValue); }else{ int i; int nSep = strlen30(p->colSeparator); @@ -765,7 +765,7 @@ static int shell_callback( if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator); for(i=0; iout,"%*s = %s%s", w, azCol[i], - azArg[i] ? azArg[i] : p->nullvalue, p->rowSeparator); + azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); } break; } @@ -782,7 +782,7 @@ static int shell_callback( if( w==0 ){ w = strlen30(azCol[i] ? azCol[i] : ""); if( w<10 ) w = 10; - n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue); + n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); if( wactualWidth) ){ @@ -832,11 +832,11 @@ static int shell_callback( } if( w<0 ){ fprintf(p->out,"%*.*s%s",-w,-w, - azArg[i] ? azArg[i] : p->nullvalue, + azArg[i] ? azArg[i] : p->nullValue, i==nArg-1 ? p->rowSeparator : " "); }else{ fprintf(p->out,"%-*.*s%s",w,w, - azArg[i] ? azArg[i] : p->nullvalue, + azArg[i] ? azArg[i] : p->nullValue, i==nArg-1 ? p->rowSeparator : " "); } } @@ -853,7 +853,7 @@ static int shell_callback( if( azArg==0 ) break; for(i=0; inullvalue; + if( z==0 ) z = p->nullValue; fprintf(p->out, "%s", z); if( iout, "%s", p->colSeparator); @@ -879,7 +879,7 @@ static int shell_callback( fprintf(p->out,""); for(i=0; iout,"\n"); } fprintf(p->out,"\n"); @@ -895,7 +895,7 @@ static int shell_callback( } if( azArg==0 ) break; for(i=0; iout, azArg[i] ? azArg[i] : p->nullvalue); + output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue); if(iout, "%s", p->colSeparator); } fprintf(p->out, "%s", p->rowSeparator); @@ -964,7 +964,7 @@ static int shell_callback( if( azArg==0 ) break; for(i=0; i0 ) fprintf(p->out, "%s", p->colSeparator); - fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); } fprintf(p->out, "%s", p->rowSeparator); break; @@ -3051,8 +3051,8 @@ static int do_meta_command(char *zLine, ShellState *p){ 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]); + sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, + "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); }else{ fprintf(stderr, "Usage: .nullvalue STRING\n"); rc = 1; @@ -3383,7 +3383,7 @@ static int do_meta_command(char *zLine, ShellState *p){ fprintf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%12.12s: %s\n","mode", modeDescr[p->mode]); fprintf(p->out,"%12.12s: ", "nullvalue"); - output_c_string(p->out, p->nullvalue); + output_c_string(p->out, p->nullValue); fprintf(p->out, "\n"); fprintf(p->out,"%12.12s: %s\n","output", strlen30(p->outfile) ? p->outfile : "stdout"); @@ -4362,7 +4362,7 @@ int main(int argc, char **argv){ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-nullvalue")==0 ){ - sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, + sqlite3_snprintf(sizeof(data.nullValue), data.nullValue, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-header")==0 ){ data.showHeader = 1; From dd11f2d9309b5e3687c82cd505ae686d27cea311 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Dec 2014 04:49:46 +0000 Subject: [PATCH 9/9] Update a comment. FossilOrigin-Name: e0e102a0bd9d07bccdb1feb95767cb81fb57c29f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8e4591a12c..e8f180d89f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sa\sstructure\smember\sto\simprove\scode\sclarity. -D 2014-12-11T03:29:14.206 +C Update\sa\scomment. +D 2014-12-11T04:49:46.125 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c f377fb8a5c73c10678ea74f3400f7913943e3d75 -F src/shell.c 3628fab3fba6490bebba7fa63989c5c410eba0a5 +F src/shell.c 1b7cb3efc5ae6fe82e36407508c4a6b00d8edde1 F src/sqlite.h.in 2e699aabd1df6042aff4265cd93bdc8812629f11 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d @@ -1227,7 +1227,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d8404340cb01af440feebd19d291eb7198cfa576 -R 46f56278d908459d592a073dfada5d9c +P d48eda16ef8a84a93de9c6f38f794aceb4a6ba0d +R 1034d99337e2b1563f22219c78cd5011 U mistachkin -Z d954c642e1623a1d799298570f596d90 +Z 59252e2fe2e00ed3f4f3196b070ae546 diff --git a/manifest.uuid b/manifest.uuid index 28bc895227..45d7bc2004 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d48eda16ef8a84a93de9c6f38f794aceb4a6ba0d \ No newline at end of file +e0e102a0bd9d07bccdb1feb95767cb81fb57c29f \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index d102d4c047..7f8a9ef3a6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -692,7 +692,7 @@ static const char needCsvQuote[] = { }; /* -** Output a single term of CSV. Actually, p->separator is used for +** Output a single term of CSV. Actually, p->colSeparator is used for ** the separator, which may or may not be a comma. p->nullValue is ** the null value. Strings are quoted if necessary. The separator ** is only issued if bSep is true.
"); - output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); fprintf(p->out,"