mirror of https://github.com/sqlite/sqlite
In the command-line shell, in CSV output mode, terminate rows with CRNL but
do not expand NL characters in data into CRNL. Provide the extra -newline command-line option and the extra argument to .separator to designate an alternative newline character sequence for CSV output. FossilOrigin-Name: 16c8ce10e1530731441e6c4538691b71564684ed
This commit is contained in:
parent
dbd9486d5b
commit
6976c2123b
16
manifest
16
manifest
|
@ -1,5 +1,5 @@
|
||||||
C Add\sexperimental\s"costmult"\slogic.\s\sOnly\senabled\swhen\scompiled\swith\n-DSQLITE_ENABLE_COSTMULT.
|
C In\sthe\scommand-line\sshell,\sin\sCSV\soutput\smode,\sterminate\srows\swith\sCRNL\sbut\ndo\snot\sexpand\sNL\scharacters\sin\sdata\sinto\sCRNL.\s\sProvide\sthe\sextra\s-newline\ncommand-line\soption\sand\sthe\sextra\sargument\sto\s.separator\sto\sdesignate\san\nalternative\snewline\scharacter\ssequence\sfor\sCSV\soutput.
|
||||||
D 2014-07-23T23:57:42.403
|
D 2014-07-24T12:09:47.370
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
|
@ -223,7 +223,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||||
F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02
|
F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02
|
||||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||||
F src/select.c 6762c62e11b504aa014edceab8886495165e3a77
|
F src/select.c 6762c62e11b504aa014edceab8886495165e3a77
|
||||||
F src/shell.c 566aee8213372a2e81ba0eb34e9759f7b2574009
|
F src/shell.c cca6ea15719f2a3f41b8a1e0030d0b67a8aae3ca
|
||||||
F src/sqlite.h.in ac4451c9da2771d2f4d702ef89722407242906d9
|
F src/sqlite.h.in ac4451c9da2771d2f4d702ef89722407242906d9
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
|
@ -819,11 +819,11 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
|
||||||
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||||
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
||||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||||
F test/shell1.test fb080d67c81e8a80a79ea04b36f127209b5bd112
|
F test/shell1.test d60946b5fde4d85fe06db7331dfe89011f564350
|
||||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||||
F test/shell5.test ef0c52952a4a96dc1d9ec3b1fa81ec897ca48154
|
F test/shell5.test 15a419cc1df21c892ed64f5596ae7a501f2816f2
|
||||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||||
|
@ -1183,7 +1183,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P e6225a7bf77a700b318563b1a854b4b3a9e031e1
|
P 729ece40885ed7f52c5981364833fc62281a388b
|
||||||
R 07ca3465b9cbcf38e018d96848d50309
|
R d4352ef214ae9bc2c731800627aed3f1
|
||||||
U drh
|
U drh
|
||||||
Z 5f4178ba82b72065a3c11af477d1e9bb
|
Z ddfb7b81152d55231f21f3e3700ae2bf
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
729ece40885ed7f52c5981364833fc62281a388b
|
16c8ce10e1530731441e6c4538691b71564684ed
|
49
src/shell.c
49
src/shell.c
|
@ -64,6 +64,7 @@
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(WIN32)
|
#if defined(_WIN32) || defined(WIN32)
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
|
# include <fcntl.h>
|
||||||
#define isatty(h) _isatty(h)
|
#define isatty(h) _isatty(h)
|
||||||
#ifndef access
|
#ifndef access
|
||||||
# define access(f,m) _access((f),(m))
|
# define access(f,m) _access((f),(m))
|
||||||
|
@ -458,6 +459,7 @@ struct callback_data {
|
||||||
int showHeader; /* True to show column names in List or Column mode */
|
int showHeader; /* True to show column names in List or Column mode */
|
||||||
char *zDestTable; /* Name of destination table when MODE_Insert */
|
char *zDestTable; /* Name of destination table when MODE_Insert */
|
||||||
char separator[20]; /* Separator character for MODE_List */
|
char separator[20]; /* Separator character for MODE_List */
|
||||||
|
char newline[20]; /* Record separator in MODE_Csv */
|
||||||
int colWidth[100]; /* Requested width of each column when in column mode*/
|
int colWidth[100]; /* Requested width of each column when in column mode*/
|
||||||
int actualWidth[100]; /* Actual width of each column */
|
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
|
||||||
|
@ -659,7 +661,8 @@ static const char needCsvQuote[] = {
|
||||||
/*
|
/*
|
||||||
** Output a single term of CSV. Actually, p->separator is used for
|
** 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 null value. Strings are quoted if necessary. The separator
|
||||||
|
** is only issued if bSep is true.
|
||||||
*/
|
*/
|
||||||
static void output_csv(struct callback_data *p, const char *z, int bSep){
|
static void output_csv(struct callback_data *p, const char *z, int bSep){
|
||||||
FILE *out = p->out;
|
FILE *out = p->out;
|
||||||
|
@ -855,17 +858,26 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MODE_Csv: {
|
case MODE_Csv: {
|
||||||
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
|
fflush(p->out);
|
||||||
|
_setmode(_fileno(p->out), _O_BINARY);
|
||||||
|
#endif
|
||||||
if( p->cnt++==0 && p->showHeader ){
|
if( p->cnt++==0 && p->showHeader ){
|
||||||
for(i=0; i<nArg; i++){
|
for(i=0; i<nArg; i++){
|
||||||
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
|
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
|
||||||
}
|
}
|
||||||
fprintf(p->out,"\n");
|
fprintf(p->out,"%s",p->newline);
|
||||||
}
|
}
|
||||||
if( azArg==0 ) break;
|
if( azArg>0 ){
|
||||||
for(i=0; i<nArg; i++){
|
for(i=0; i<nArg; i++){
|
||||||
output_csv(p, azArg[i], i<nArg-1);
|
output_csv(p, azArg[i], i<nArg-1);
|
||||||
|
}
|
||||||
|
fprintf(p->out,"%s",p->newline);
|
||||||
}
|
}
|
||||||
fprintf(p->out,"\n");
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
|
fflush(p->out);
|
||||||
|
_setmode(_fileno(p->out), _O_TEXT);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MODE_Insert: {
|
case MODE_Insert: {
|
||||||
|
@ -1619,7 +1631,8 @@ static char zHelp[] =
|
||||||
".schema ?TABLE? Show the CREATE statements\n"
|
".schema ?TABLE? Show the CREATE statements\n"
|
||||||
" If TABLE specified, only show tables matching\n"
|
" If TABLE specified, only show tables matching\n"
|
||||||
" LIKE pattern TABLE.\n"
|
" LIKE pattern TABLE.\n"
|
||||||
".separator STRING Change separator used by output mode and .import\n"
|
".separator STRING ?NL? Change separator used by output mode and .import\n"
|
||||||
|
" NL is the end-of-line mark for CSV\n"
|
||||||
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||||
".show Show the current values for various settings\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"
|
||||||
|
@ -2751,6 +2764,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||||
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
|
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
|
||||||
p->mode = MODE_Csv;
|
p->mode = MODE_Csv;
|
||||||
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
|
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
|
||||||
|
sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
|
||||||
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
|
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
|
||||||
p->mode = MODE_List;
|
p->mode = MODE_List;
|
||||||
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
|
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
|
||||||
|
@ -3029,13 +3043,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
|
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
|
||||||
if( nArg==2 ){
|
if( nArg<2 || nArg>3 ){
|
||||||
sqlite3_snprintf(sizeof(p->separator), p->separator,
|
fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
|
||||||
"%.*s", (int)sizeof(p->separator)-1, azArg[1]);
|
|
||||||
}else{
|
|
||||||
fprintf(stderr, "Usage: .separator STRING\n");
|
|
||||||
rc = 1;
|
rc = 1;
|
||||||
}
|
}
|
||||||
|
if( nArg>=2 ){
|
||||||
|
sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
|
||||||
|
}
|
||||||
|
if( nArg>=3 ){
|
||||||
|
sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
|
||||||
|
}
|
||||||
}else
|
}else
|
||||||
|
|
||||||
if( c=='s'
|
if( c=='s'
|
||||||
|
@ -3076,6 +3093,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||||
strlen30(p->outfile) ? p->outfile : "stdout");
|
strlen30(p->outfile) ? p->outfile : "stdout");
|
||||||
fprintf(p->out,"%9.9s: ", "separator");
|
fprintf(p->out,"%9.9s: ", "separator");
|
||||||
output_c_string(p->out, p->separator);
|
output_c_string(p->out, p->separator);
|
||||||
|
fprintf(p->out," ");
|
||||||
|
output_c_string(p->out, p->newline);
|
||||||
fprintf(p->out, "\n");
|
fprintf(p->out, "\n");
|
||||||
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
|
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
|
||||||
fprintf(p->out,"%9.9s: ","width");
|
fprintf(p->out,"%9.9s: ","width");
|
||||||
|
@ -3692,6 +3711,7 @@ static const char zOptions[] =
|
||||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||||
" -multiplex enable the multiplexor VFS\n"
|
" -multiplex enable the multiplexor VFS\n"
|
||||||
#endif
|
#endif
|
||||||
|
" -newline SEP set newline character(s) for CSV\n"
|
||||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||||
" -separator SEP set output field separator. Default: '|'\n"
|
" -separator SEP set output field separator. Default: '|'\n"
|
||||||
" -stats print memory stats before each finalize\n"
|
" -stats print memory stats before each finalize\n"
|
||||||
|
@ -3721,6 +3741,7 @@ static void main_init(struct callback_data *data) {
|
||||||
memset(data, 0, sizeof(*data));
|
memset(data, 0, sizeof(*data));
|
||||||
data->mode = MODE_List;
|
data->mode = MODE_List;
|
||||||
memcpy(data->separator,"|", 2);
|
memcpy(data->separator,"|", 2);
|
||||||
|
memcpy(data->newline,"\r\n", 3);
|
||||||
data->showHeader = 0;
|
data->showHeader = 0;
|
||||||
sqlite3_config(SQLITE_CONFIG_URI, 1);
|
sqlite3_config(SQLITE_CONFIG_URI, 1);
|
||||||
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
|
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
|
||||||
|
@ -3813,6 +3834,7 @@ int main(int argc, char **argv){
|
||||||
if( z[1]=='-' ) z++;
|
if( z[1]=='-' ) z++;
|
||||||
if( strcmp(z,"-separator")==0
|
if( strcmp(z,"-separator")==0
|
||||||
|| strcmp(z,"-nullvalue")==0
|
|| strcmp(z,"-nullvalue")==0
|
||||||
|
|| strcmp(z,"-newline")==0
|
||||||
|| strcmp(z,"-cmd")==0
|
|| strcmp(z,"-cmd")==0
|
||||||
){
|
){
|
||||||
(void)cmdline_option_value(argc, argv, ++i);
|
(void)cmdline_option_value(argc, argv, ++i);
|
||||||
|
@ -3922,6 +3944,9 @@ int main(int argc, char **argv){
|
||||||
}else if( strcmp(z,"-separator")==0 ){
|
}else if( strcmp(z,"-separator")==0 ){
|
||||||
sqlite3_snprintf(sizeof(data.separator), data.separator,
|
sqlite3_snprintf(sizeof(data.separator), data.separator,
|
||||||
"%s",cmdline_option_value(argc,argv,++i));
|
"%s",cmdline_option_value(argc,argv,++i));
|
||||||
|
}else if( strcmp(z,"-newline")==0 ){
|
||||||
|
sqlite3_snprintf(sizeof(data.newline), data.newline,
|
||||||
|
"%s",cmdline_option_value(argc,argv,++i));
|
||||||
}else if( strcmp(z,"-nullvalue")==0 ){
|
}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));
|
"%s",cmdline_option_value(argc,argv,++i));
|
||||||
|
|
|
@ -588,14 +588,17 @@ db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
|
||||||
# .separator STRING Change separator used by output mode and .import
|
# .separator STRING Change separator used by output mode and .import
|
||||||
do_test shell1-3.22.1 {
|
do_test shell1-3.22.1 {
|
||||||
catchcmd "test.db" ".separator"
|
catchcmd "test.db" ".separator"
|
||||||
} {1 {Usage: .separator STRING}}
|
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||||
do_test shell1-3.22.2 {
|
do_test shell1-3.22.2 {
|
||||||
catchcmd "test.db" ".separator FOO"
|
catchcmd "test.db" ".separator FOO"
|
||||||
} {0 {}}
|
} {0 {}}
|
||||||
do_test shell1-3.22.3 {
|
do_test shell1-3.22.3 {
|
||||||
|
catchcmd "test.db" ".separator ABC XYZ"
|
||||||
|
} {0 {}}
|
||||||
|
do_test shell1-3.22.4 {
|
||||||
# too many arguments
|
# too many arguments
|
||||||
catchcmd "test.db" ".separator FOO BAD"
|
catchcmd "test.db" ".separator FOO BAD BAD2"
|
||||||
} {1 {Usage: .separator STRING}}
|
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||||
|
|
||||||
# .show Show the current values for various settings
|
# .show Show the current values for various settings
|
||||||
do_test shell1-3.23.1 {
|
do_test shell1-3.23.1 {
|
||||||
|
|
|
@ -55,14 +55,17 @@ do_test shell5-1.1.3 {
|
||||||
# .separator STRING Change separator used by output mode and .import
|
# .separator STRING Change separator used by output mode and .import
|
||||||
do_test shell5-1.2.1 {
|
do_test shell5-1.2.1 {
|
||||||
catchcmd "test.db" ".separator"
|
catchcmd "test.db" ".separator"
|
||||||
} {1 {Usage: .separator STRING}}
|
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||||
do_test shell5-1.2.2 {
|
do_test shell5-1.2.2 {
|
||||||
catchcmd "test.db" ".separator FOO"
|
catchcmd "test.db" ".separator ONE"
|
||||||
} {0 {}}
|
} {0 {}}
|
||||||
do_test shell5-1.2.3 {
|
do_test shell5-1.2.3 {
|
||||||
|
catchcmd "test.db" ".separator ONE TWO"
|
||||||
|
} {0 {}}
|
||||||
|
do_test shell5-1.2.4 {
|
||||||
# too many arguments
|
# too many arguments
|
||||||
catchcmd "test.db" ".separator FOO BAD"
|
catchcmd "test.db" ".separator ONE TWO THREE"
|
||||||
} {1 {Usage: .separator STRING}}
|
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||||
|
|
||||||
# separator should default to "|"
|
# separator should default to "|"
|
||||||
do_test shell5-1.3.1 {
|
do_test shell5-1.3.1 {
|
||||||
|
|
Loading…
Reference in New Issue