Fossil SCM
Cherry-pick [http://www.sqlite.org/src/info/2a9ea9b4a7d6904efb2112e32efe84123dfa75d7|2a9ea9b4a7] : In the command-line shell, make sure stderr is unbuffered so that it automatically flushes. So, this works for "fossil sqlite" as well. (actually, just by copying latest "shell.c" from SQLite)
Commit
bcd7b488a2e11a7a904b249c2d41b6ca0b51c301
Parent
09fe92ad728cf5f…
1 file changed
+30
-10
+30
-10
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -104,10 +104,30 @@ | ||
| 104 | 104 | /* ctype macros that work with signed characters */ |
| 105 | 105 | #define IsSpace(X) isspace((unsigned char)X) |
| 106 | 106 | #define IsDigit(X) isdigit((unsigned char)X) |
| 107 | 107 | #define ToLower(X) (char)tolower((unsigned char)X) |
| 108 | 108 | |
| 109 | +/* On Windows, we normally run with output mode of TEXT so that \n characters | |
| 110 | +** are automatically translated into \r\n. However, this behavior needs | |
| 111 | +** to be disabled in some cases (ex: when generating CSV output and when | |
| 112 | +** rendering quoted strings that contain \n characters). The following | |
| 113 | +** routines take care of that. | |
| 114 | +*/ | |
| 115 | +#if defined(_WIN32) || defined(WIN32) | |
| 116 | +static setBinaryMode(FILE *out){ | |
| 117 | + fflush(out); | |
| 118 | + _setmode(_fileno(out), _O_BINARY); | |
| 119 | +} | |
| 120 | +static setTextMode(FILE *out){ | |
| 121 | + fflush(out); | |
| 122 | + _setmode(_fileno(out), _O_TEXT); | |
| 123 | +} | |
| 124 | +#else | |
| 125 | +# define setBinaryMode(X) | |
| 126 | +# define setTextMode(X) | |
| 127 | +#endif | |
| 128 | + | |
| 109 | 129 | |
| 110 | 130 | /* True if the timer is enabled */ |
| 111 | 131 | static int enableTimer = 0; |
| 112 | 132 | |
| 113 | 133 | /* Return the current wall-clock time */ |
| @@ -582,10 +602,11 @@ | ||
| 582 | 602 | ** Output the given string as a quoted string using SQL quoting conventions. |
| 583 | 603 | */ |
| 584 | 604 | static void output_quoted_string(FILE *out, const char *z){ |
| 585 | 605 | int i; |
| 586 | 606 | int nSingle = 0; |
| 607 | + setBinaryMode(out); | |
| 587 | 608 | for(i=0; z[i]; i++){ |
| 588 | 609 | if( z[i]=='\'' ) nSingle++; |
| 589 | 610 | } |
| 590 | 611 | if( nSingle==0 ){ |
| 591 | 612 | fprintf(out,"'%s'",z); |
| @@ -604,10 +625,11 @@ | ||
| 604 | 625 | break; |
| 605 | 626 | } |
| 606 | 627 | } |
| 607 | 628 | fprintf(out,"'"); |
| 608 | 629 | } |
| 630 | + setTextMode(out); | |
| 609 | 631 | } |
| 610 | 632 | |
| 611 | 633 | /* |
| 612 | 634 | ** Output the given string as a quoted according to C or TCL quoting rules. |
| 613 | 635 | */ |
| @@ -906,14 +928,11 @@ | ||
| 906 | 928 | } |
| 907 | 929 | fprintf(p->out, "%s", p->rowSeparator); |
| 908 | 930 | break; |
| 909 | 931 | } |
| 910 | 932 | case MODE_Csv: { |
| 911 | -#if defined(WIN32) || defined(_WIN32) | |
| 912 | - fflush(p->out); | |
| 913 | - _setmode(_fileno(p->out), _O_BINARY); | |
| 914 | -#endif | |
| 933 | + setBinaryMode(p->out); | |
| 915 | 934 | if( p->cnt++==0 && p->showHeader ){ |
| 916 | 935 | for(i=0; i<nArg; i++){ |
| 917 | 936 | output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
| 918 | 937 | } |
| 919 | 938 | fprintf(p->out, "%s", p->rowSeparator); |
| @@ -922,14 +941,11 @@ | ||
| 922 | 941 | for(i=0; i<nArg; i++){ |
| 923 | 942 | output_csv(p, azArg[i], i<nArg-1); |
| 924 | 943 | } |
| 925 | 944 | fprintf(p->out, "%s", p->rowSeparator); |
| 926 | 945 | } |
| 927 | -#if defined(WIN32) || defined(_WIN32) | |
| 928 | - fflush(p->out); | |
| 929 | - _setmode(_fileno(p->out), _O_TEXT); | |
| 930 | -#endif | |
| 946 | + setTextMode(p->out); | |
| 931 | 947 | break; |
| 932 | 948 | } |
| 933 | 949 | case MODE_Insert: { |
| 934 | 950 | p->cnt++; |
| 935 | 951 | if( azArg==0 ) break; |
| @@ -3322,11 +3338,11 @@ | ||
| 3322 | 3338 | |
| 3323 | 3339 | |
| 3324 | 3340 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 3325 | 3341 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 3326 | 3342 | extern int sqlite3SelectTrace; |
| 3327 | - sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; | |
| 3343 | + sqlite3SelectTrace = integerValue(azArg[1]); | |
| 3328 | 3344 | }else |
| 3329 | 3345 | #endif |
| 3330 | 3346 | |
| 3331 | 3347 | |
| 3332 | 3348 | #ifdef SQLITE_DEBUG |
| @@ -3528,10 +3544,11 @@ | ||
| 3528 | 3544 | { "reserve", SQLITE_TESTCTRL_RESERVE }, |
| 3529 | 3545 | { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, |
| 3530 | 3546 | { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, |
| 3531 | 3547 | { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, |
| 3532 | 3548 | { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, |
| 3549 | + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT }, | |
| 3533 | 3550 | }; |
| 3534 | 3551 | int testctrl = -1; |
| 3535 | 3552 | int rc = 0; |
| 3536 | 3553 | int i, n; |
| 3537 | 3554 | open_db(p, 0); |
| @@ -3594,11 +3611,12 @@ | ||
| 3594 | 3611 | } |
| 3595 | 3612 | break; |
| 3596 | 3613 | |
| 3597 | 3614 | /* sqlite3_test_control(int, int) */ |
| 3598 | 3615 | case SQLITE_TESTCTRL_ASSERT: |
| 3599 | - case SQLITE_TESTCTRL_ALWAYS: | |
| 3616 | + case SQLITE_TESTCTRL_ALWAYS: | |
| 3617 | + case SQLITE_TESTCTRL_NEVER_CORRUPT: | |
| 3600 | 3618 | if( nArg==3 ){ |
| 3601 | 3619 | int opt = booleanValue(azArg[2]); |
| 3602 | 3620 | rc = sqlite3_test_control(testctrl, opt); |
| 3603 | 3621 | fprintf(p->out, "%d (0x%08x)\n", rc, rc); |
| 3604 | 3622 | } else { |
| @@ -4185,10 +4203,12 @@ | ||
| 4185 | 4203 | fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", |
| 4186 | 4204 | sqlite3_sourceid(), SQLITE_SOURCE_ID); |
| 4187 | 4205 | exit(1); |
| 4188 | 4206 | } |
| 4189 | 4207 | #endif |
| 4208 | + setBinaryMode(stdin); | |
| 4209 | + setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ | |
| 4190 | 4210 | Argv0 = argv[0]; |
| 4191 | 4211 | main_init(&data); |
| 4192 | 4212 | stdin_is_interactive = isatty(0); |
| 4193 | 4213 | |
| 4194 | 4214 | /* Make sure we have a valid signal handler early, before anything |
| 4195 | 4215 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -104,10 +104,30 @@ | |
| 104 | /* ctype macros that work with signed characters */ |
| 105 | #define IsSpace(X) isspace((unsigned char)X) |
| 106 | #define IsDigit(X) isdigit((unsigned char)X) |
| 107 | #define ToLower(X) (char)tolower((unsigned char)X) |
| 108 | |
| 109 | |
| 110 | /* True if the timer is enabled */ |
| 111 | static int enableTimer = 0; |
| 112 | |
| 113 | /* Return the current wall-clock time */ |
| @@ -582,10 +602,11 @@ | |
| 582 | ** Output the given string as a quoted string using SQL quoting conventions. |
| 583 | */ |
| 584 | static void output_quoted_string(FILE *out, const char *z){ |
| 585 | int i; |
| 586 | int nSingle = 0; |
| 587 | for(i=0; z[i]; i++){ |
| 588 | if( z[i]=='\'' ) nSingle++; |
| 589 | } |
| 590 | if( nSingle==0 ){ |
| 591 | fprintf(out,"'%s'",z); |
| @@ -604,10 +625,11 @@ | |
| 604 | break; |
| 605 | } |
| 606 | } |
| 607 | fprintf(out,"'"); |
| 608 | } |
| 609 | } |
| 610 | |
| 611 | /* |
| 612 | ** Output the given string as a quoted according to C or TCL quoting rules. |
| 613 | */ |
| @@ -906,14 +928,11 @@ | |
| 906 | } |
| 907 | fprintf(p->out, "%s", p->rowSeparator); |
| 908 | break; |
| 909 | } |
| 910 | case MODE_Csv: { |
| 911 | #if defined(WIN32) || defined(_WIN32) |
| 912 | fflush(p->out); |
| 913 | _setmode(_fileno(p->out), _O_BINARY); |
| 914 | #endif |
| 915 | if( p->cnt++==0 && p->showHeader ){ |
| 916 | for(i=0; i<nArg; i++){ |
| 917 | output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
| 918 | } |
| 919 | fprintf(p->out, "%s", p->rowSeparator); |
| @@ -922,14 +941,11 @@ | |
| 922 | for(i=0; i<nArg; i++){ |
| 923 | output_csv(p, azArg[i], i<nArg-1); |
| 924 | } |
| 925 | fprintf(p->out, "%s", p->rowSeparator); |
| 926 | } |
| 927 | #if defined(WIN32) || defined(_WIN32) |
| 928 | fflush(p->out); |
| 929 | _setmode(_fileno(p->out), _O_TEXT); |
| 930 | #endif |
| 931 | break; |
| 932 | } |
| 933 | case MODE_Insert: { |
| 934 | p->cnt++; |
| 935 | if( azArg==0 ) break; |
| @@ -3322,11 +3338,11 @@ | |
| 3322 | |
| 3323 | |
| 3324 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 3325 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 3326 | extern int sqlite3SelectTrace; |
| 3327 | sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; |
| 3328 | }else |
| 3329 | #endif |
| 3330 | |
| 3331 | |
| 3332 | #ifdef SQLITE_DEBUG |
| @@ -3528,10 +3544,11 @@ | |
| 3528 | { "reserve", SQLITE_TESTCTRL_RESERVE }, |
| 3529 | { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, |
| 3530 | { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, |
| 3531 | { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, |
| 3532 | { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, |
| 3533 | }; |
| 3534 | int testctrl = -1; |
| 3535 | int rc = 0; |
| 3536 | int i, n; |
| 3537 | open_db(p, 0); |
| @@ -3594,11 +3611,12 @@ | |
| 3594 | } |
| 3595 | break; |
| 3596 | |
| 3597 | /* sqlite3_test_control(int, int) */ |
| 3598 | case SQLITE_TESTCTRL_ASSERT: |
| 3599 | case SQLITE_TESTCTRL_ALWAYS: |
| 3600 | if( nArg==3 ){ |
| 3601 | int opt = booleanValue(azArg[2]); |
| 3602 | rc = sqlite3_test_control(testctrl, opt); |
| 3603 | fprintf(p->out, "%d (0x%08x)\n", rc, rc); |
| 3604 | } else { |
| @@ -4185,10 +4203,12 @@ | |
| 4185 | fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", |
| 4186 | sqlite3_sourceid(), SQLITE_SOURCE_ID); |
| 4187 | exit(1); |
| 4188 | } |
| 4189 | #endif |
| 4190 | Argv0 = argv[0]; |
| 4191 | main_init(&data); |
| 4192 | stdin_is_interactive = isatty(0); |
| 4193 | |
| 4194 | /* Make sure we have a valid signal handler early, before anything |
| 4195 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -104,10 +104,30 @@ | |
| 104 | /* ctype macros that work with signed characters */ |
| 105 | #define IsSpace(X) isspace((unsigned char)X) |
| 106 | #define IsDigit(X) isdigit((unsigned char)X) |
| 107 | #define ToLower(X) (char)tolower((unsigned char)X) |
| 108 | |
| 109 | /* On Windows, we normally run with output mode of TEXT so that \n characters |
| 110 | ** are automatically translated into \r\n. However, this behavior needs |
| 111 | ** to be disabled in some cases (ex: when generating CSV output and when |
| 112 | ** rendering quoted strings that contain \n characters). The following |
| 113 | ** routines take care of that. |
| 114 | */ |
| 115 | #if defined(_WIN32) || defined(WIN32) |
| 116 | static setBinaryMode(FILE *out){ |
| 117 | fflush(out); |
| 118 | _setmode(_fileno(out), _O_BINARY); |
| 119 | } |
| 120 | static setTextMode(FILE *out){ |
| 121 | fflush(out); |
| 122 | _setmode(_fileno(out), _O_TEXT); |
| 123 | } |
| 124 | #else |
| 125 | # define setBinaryMode(X) |
| 126 | # define setTextMode(X) |
| 127 | #endif |
| 128 | |
| 129 | |
| 130 | /* True if the timer is enabled */ |
| 131 | static int enableTimer = 0; |
| 132 | |
| 133 | /* Return the current wall-clock time */ |
| @@ -582,10 +602,11 @@ | |
| 602 | ** Output the given string as a quoted string using SQL quoting conventions. |
| 603 | */ |
| 604 | static void output_quoted_string(FILE *out, const char *z){ |
| 605 | int i; |
| 606 | int nSingle = 0; |
| 607 | setBinaryMode(out); |
| 608 | for(i=0; z[i]; i++){ |
| 609 | if( z[i]=='\'' ) nSingle++; |
| 610 | } |
| 611 | if( nSingle==0 ){ |
| 612 | fprintf(out,"'%s'",z); |
| @@ -604,10 +625,11 @@ | |
| 625 | break; |
| 626 | } |
| 627 | } |
| 628 | fprintf(out,"'"); |
| 629 | } |
| 630 | setTextMode(out); |
| 631 | } |
| 632 | |
| 633 | /* |
| 634 | ** Output the given string as a quoted according to C or TCL quoting rules. |
| 635 | */ |
| @@ -906,14 +928,11 @@ | |
| 928 | } |
| 929 | fprintf(p->out, "%s", p->rowSeparator); |
| 930 | break; |
| 931 | } |
| 932 | case MODE_Csv: { |
| 933 | setBinaryMode(p->out); |
| 934 | if( p->cnt++==0 && p->showHeader ){ |
| 935 | for(i=0; i<nArg; i++){ |
| 936 | output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
| 937 | } |
| 938 | fprintf(p->out, "%s", p->rowSeparator); |
| @@ -922,14 +941,11 @@ | |
| 941 | for(i=0; i<nArg; i++){ |
| 942 | output_csv(p, azArg[i], i<nArg-1); |
| 943 | } |
| 944 | fprintf(p->out, "%s", p->rowSeparator); |
| 945 | } |
| 946 | setTextMode(p->out); |
| 947 | break; |
| 948 | } |
| 949 | case MODE_Insert: { |
| 950 | p->cnt++; |
| 951 | if( azArg==0 ) break; |
| @@ -3322,11 +3338,11 @@ | |
| 3338 | |
| 3339 | |
| 3340 | #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 3341 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
| 3342 | extern int sqlite3SelectTrace; |
| 3343 | sqlite3SelectTrace = integerValue(azArg[1]); |
| 3344 | }else |
| 3345 | #endif |
| 3346 | |
| 3347 | |
| 3348 | #ifdef SQLITE_DEBUG |
| @@ -3528,10 +3544,11 @@ | |
| 3544 | { "reserve", SQLITE_TESTCTRL_RESERVE }, |
| 3545 | { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, |
| 3546 | { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, |
| 3547 | { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, |
| 3548 | { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, |
| 3549 | { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT }, |
| 3550 | }; |
| 3551 | int testctrl = -1; |
| 3552 | int rc = 0; |
| 3553 | int i, n; |
| 3554 | open_db(p, 0); |
| @@ -3594,11 +3611,12 @@ | |
| 3611 | } |
| 3612 | break; |
| 3613 | |
| 3614 | /* sqlite3_test_control(int, int) */ |
| 3615 | case SQLITE_TESTCTRL_ASSERT: |
| 3616 | case SQLITE_TESTCTRL_ALWAYS: |
| 3617 | case SQLITE_TESTCTRL_NEVER_CORRUPT: |
| 3618 | if( nArg==3 ){ |
| 3619 | int opt = booleanValue(azArg[2]); |
| 3620 | rc = sqlite3_test_control(testctrl, opt); |
| 3621 | fprintf(p->out, "%d (0x%08x)\n", rc, rc); |
| 3622 | } else { |
| @@ -4185,10 +4203,12 @@ | |
| 4203 | fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", |
| 4204 | sqlite3_sourceid(), SQLITE_SOURCE_ID); |
| 4205 | exit(1); |
| 4206 | } |
| 4207 | #endif |
| 4208 | setBinaryMode(stdin); |
| 4209 | setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ |
| 4210 | Argv0 = argv[0]; |
| 4211 | main_init(&data); |
| 4212 | stdin_is_interactive = isatty(0); |
| 4213 | |
| 4214 | /* Make sure we have a valid signal handler early, before anything |
| 4215 |