mirror of https://github.com/sqlite/sqlite
Some experimental command line shell input/output enhancements.
FossilOrigin-Name: 25e99f3fe5e4c90e92554b8ac6cd6a83a8d01a6a
This commit is contained in:
parent
5d907be5c9
commit
f21979df76
21
manifest
21
manifest
|
@ -1,5 +1,5 @@
|
|||
C Set\sthe\scommand-line\sshell\sstdin\sto\sbinary\smode\son\swindows.
|
||||
D 2015-01-18T01:50:54.333
|
||||
C Some\sexperimental\scommand\sline\sshell\sinput/output\senhancements.
|
||||
D 2015-01-18T05:35:01.547
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -230,7 +230,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
|||
F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c e4c38c75e36f28aed80a69a725d888751bfd53df
|
||||
F src/shell.c 96c40c85467552025d81505310efcf3679303d3a
|
||||
F src/shell.c b976fd2b3dd3c097e7749f26b9cb8c6ca75985a8
|
||||
F src/sqlite.h.in 9dfc99d6533d36d6a549c4f3f01cacc8be956ada
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
|
@ -855,7 +855,7 @@ 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 cdeb849acc2c37aada70d084564b0cc0a2c7df08
|
||||
F test/shell1.test 4c16272bc959443fe3848d1370e686694b10fdaf
|
||||
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||
|
@ -905,7 +905,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
|||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl ed77454e6c7b40eb501db7e79d1c6fbfd3eebbff
|
||||
F test/tester.tcl 51211254f2ee2340d3e4fa0a83bd5381b9e1a227
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
|
@ -1236,7 +1236,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 ceac571f53bdbc02616b21a4404cb1250030dea8
|
||||
R af1132932e63d89318ed108ce444bb3a
|
||||
U drh
|
||||
Z 8c65f5a7bb0fabe2bc52b8a9296117bf
|
||||
P 80541e8b94b713e8f9e588ae047ffc5ae804ef1c
|
||||
R b03241b729782f3438422b692742f278
|
||||
T *branch * expShell
|
||||
T *sym-expShell *
|
||||
T -sym-trunk *
|
||||
U mistachkin
|
||||
Z 971bfa7ec1c0dafc699fba1587f31a66
|
||||
|
|
|
@ -1 +1 @@
|
|||
80541e8b94b713e8f9e588ae047ffc5ae804ef1c
|
||||
25e99f3fe5e4c90e92554b8ac6cd6a83a8d01a6a
|
62
src/shell.c
62
src/shell.c
|
@ -746,6 +746,22 @@ static void interrupt_handler(int NotUsed){
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
/*
|
||||
** This routine is used to adjust the file translation mode for the output
|
||||
** file. It is only used on Windows.
|
||||
*/
|
||||
static void enable_binary_output(
|
||||
ShellState *p,
|
||||
int enable
|
||||
){
|
||||
fflush(p->out);
|
||||
_setmode(_fileno(p->out), enable ? _O_BINARY : _O_TEXT);
|
||||
}
|
||||
#else
|
||||
#define enable_binary_output(p,e)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This is the callback routine that the shell
|
||||
** invokes for each row of a query result.
|
||||
|
@ -908,10 +924,7 @@ static int shell_callback(
|
|||
break;
|
||||
}
|
||||
case MODE_Csv: {
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
fflush(p->out);
|
||||
_setmode(_fileno(p->out), _O_BINARY);
|
||||
#endif
|
||||
enable_binary_output(p, 1);
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
|
||||
|
@ -924,10 +937,7 @@ static int shell_callback(
|
|||
}
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
fflush(p->out);
|
||||
_setmode(_fileno(p->out), _O_TEXT);
|
||||
#endif
|
||||
enable_binary_output(p, 0);
|
||||
break;
|
||||
}
|
||||
case MODE_Insert: {
|
||||
|
@ -1715,6 +1725,7 @@ static int run_schema_dump_query(
|
|||
static char zHelp[] =
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
".databases List names and files of attached databases\n"
|
||||
".dump ?TABLE? ... Dump the database in an SQL text format\n"
|
||||
|
@ -1875,12 +1886,18 @@ static void open_db(ShellState *p, int keepAlive){
|
|||
/*
|
||||
** Do C-language style dequoting.
|
||||
**
|
||||
** \a -> alarm
|
||||
** \b -> backspace
|
||||
** \t -> tab
|
||||
** \n -> newline
|
||||
** \v -> vertical tab
|
||||
** \f -> form feed
|
||||
** \r -> carriage return
|
||||
** \s -> space
|
||||
** \" -> "
|
||||
** \NNN -> ascii character NNN in octal
|
||||
** \' -> '
|
||||
** \\ -> backslash
|
||||
** \NNN -> ascii character NNN in octal
|
||||
*/
|
||||
static void resolve_backslashes(char *z){
|
||||
int i, j;
|
||||
|
@ -1889,12 +1906,24 @@ static void resolve_backslashes(char *z){
|
|||
for(i=j=0; (c = z[i])!=0; i++, j++){
|
||||
if( c=='\\' ){
|
||||
c = z[++i];
|
||||
if( c=='n' ){
|
||||
c = '\n';
|
||||
if( c=='a' ){
|
||||
c = '\a';
|
||||
}else if( c=='b' ){
|
||||
c = '\b';
|
||||
}else if( c=='t' ){
|
||||
c = '\t';
|
||||
}else if( c=='n' ){
|
||||
c = '\n';
|
||||
}else if( c=='v' ){
|
||||
c = '\v';
|
||||
}else if( c=='f' ){
|
||||
c = '\f';
|
||||
}else if( c=='r' ){
|
||||
c = '\r';
|
||||
}else if( c=='"' ){
|
||||
c = '"';
|
||||
}else if( c=='\'' ){
|
||||
c = '\'';
|
||||
}else if( c=='\\' ){
|
||||
c = '\\';
|
||||
}else if( c>='0' && c<='7' ){
|
||||
|
@ -2517,6 +2546,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
enable_binary_output(p, booleanValue(azArg[1]));
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .binary on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
/* The undocumented ".breakpoint" command causes a call to the no-op
|
||||
** routine named test_breakpoint().
|
||||
*/
|
||||
|
@ -4177,7 +4215,7 @@ int main(int argc, char **argv){
|
|||
}
|
||||
#endif
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
_setmode(0, _O_BINARY);
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
Argv0 = argv[0];
|
||||
main_init(&data);
|
||||
|
|
|
@ -815,4 +815,37 @@ do_test shell1-4.6 {
|
|||
";"
|
||||
"$"} 7}
|
||||
|
||||
# Test using arbitrary byte data with the shell via standard input/output.
|
||||
#
|
||||
do_test shell1-5.0 {
|
||||
#
|
||||
# NOTE: Skip NUL byte because it appears to be incompatible with command
|
||||
# shell argument parsing.
|
||||
#
|
||||
for {set i 1} {$i < 256} {incr i} {
|
||||
#
|
||||
# NOTE: Due to how the Tcl [exec] command works on Windows (i.e. where
|
||||
# it treats command channels opened for it as textual ones), the
|
||||
# carriage-return and end-of-file characters cannot be used here.
|
||||
#
|
||||
if {$tcl_platform(platform)=="windows" && ($i == 0x0D || $i == 0x1A)} {
|
||||
continue
|
||||
}
|
||||
set hex [format %02X $i]
|
||||
set char [subst \\x$hex]; set oldChar $char
|
||||
set char [string map [list \
|
||||
\a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \
|
||||
" " "\" \"" \" \\\" ' \"'\" \\ \\\\] $char]
|
||||
set x [catchcmdex test.db ".print $char\r\n"]
|
||||
set code [lindex $x 0]
|
||||
set res [lindex $x 1]
|
||||
if {$code ne "0"} {
|
||||
error "failed with error: $res"
|
||||
}
|
||||
if {$res ne "$oldChar\n"} {
|
||||
error "failed with byte $hex mismatch"
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -666,6 +666,15 @@ proc do_test {name cmd expected} {
|
|||
flush stdout
|
||||
}
|
||||
|
||||
proc dumpbytes {s} {
|
||||
set r ""
|
||||
for {set i 0} {$i < [string length $s]} {incr i} {
|
||||
if {$i > 0} {append r " "}
|
||||
append r [format %02X [scan [string index $s $i] %c]]
|
||||
}
|
||||
return $r
|
||||
}
|
||||
|
||||
proc catchcmd {db {cmd ""}} {
|
||||
global CLI
|
||||
set out [open cmds.txt w]
|
||||
|
@ -676,6 +685,30 @@ proc catchcmd {db {cmd ""}} {
|
|||
list $rc $msg
|
||||
}
|
||||
|
||||
proc catchcmdex {db {cmd ""}} {
|
||||
global CLI
|
||||
set out [open cmds.txt w]
|
||||
fconfigure $out -encoding binary -translation binary
|
||||
puts -nonewline $out $cmd
|
||||
close $out
|
||||
set line "exec -keepnewline -- $CLI $db < cmds.txt"
|
||||
set chans [list stdin stdout stderr]
|
||||
foreach chan $chans {
|
||||
catch {
|
||||
set modes($chan) [fconfigure $chan]
|
||||
fconfigure $chan -encoding binary -translation binary -buffering none
|
||||
}
|
||||
}
|
||||
set rc [catch { eval $line } msg]
|
||||
foreach chan $chans {
|
||||
catch {
|
||||
eval fconfigure [list $chan] $modes($chan)
|
||||
}
|
||||
}
|
||||
# puts [dumpbytes $msg]
|
||||
list $rc $msg
|
||||
}
|
||||
|
||||
proc filepath_normalize {p} {
|
||||
# test cases should be written to assume "unix"-like file paths
|
||||
if {$::tcl_platform(platform)!="unix"} {
|
||||
|
|
Loading…
Reference in New Issue