| | @@ -343,31 +343,25 @@ |
| 343 | 343 | #include <stdarg.h> |
| 344 | 344 | #include <io.h> |
| 345 | 345 | #include <fcntl.h> |
| 346 | 346 | |
| 347 | 347 | /* |
| 348 | | -** If the SQLITE_U8TEXT_ONLY option is defined, then only use |
| 349 | | -** _O_U8TEXT, _O_WTEXT, and similar together with the UTF-16 |
| 350 | | -** interfaces to the Windows CRT. The use of ANSI-only routines |
| 351 | | -** like fputs() and ANSI modes like _O_TEXT and _O_BINARY is |
| 352 | | -** avoided. |
| 353 | | -** |
| 354 | | -** The downside of using SQLITE_U8TEXT_ONLY is that it becomes |
| 355 | | -** impossible to output a bare newline character (0x0a) - that is, |
| 356 | | -** a newline that is not preceded by a carriage return (0x0d). |
| 357 | | -** And without that capability, sometimes the output will be slightly |
| 358 | | -** incorrect, as extra 0x0d characters will have been inserted where |
| 359 | | -** they do not belong. |
| 360 | | -** |
| 361 | | -** The SQLITE_U8TEXT_STDIO compile-time option is a compromise. |
| 362 | | -** It always enables _O_WTEXT or similar for stdin, stdout, stderr, |
| 363 | | -** but allows other streams to be _O_TEXT and/or O_BINARY. The |
| 364 | | -** SQLITE_U8TEXT_STDIO option has the same downside as SQLITE_U8TEXT_ONLY |
| 365 | | -** in that stray 0x0d characters might appear where they ought not, but |
| 366 | | -** at least with this option those characters only appear on standard |
| 367 | | -** I/O streams, and not on new streams that might be created by the |
| 368 | | -** application using sqlite3_fopen() or sqlite3_popen(). |
| 348 | +** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT |
| 349 | +** when appropriate on all output. (Sometimes use O_BINARY when |
| 350 | +** rendering ASCII text in cases where NL-to-CRLF expansion would |
| 351 | +** not be correct.) |
| 352 | +** |
| 353 | +** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT |
| 354 | +** when appropriate when writing to stdout or stderr. Use O_BINARY |
| 355 | +** or O_TEXT (depending on things like the .mode and the .crnl setting |
| 356 | +** in the CLI, or other context clues in other applications) for all |
| 357 | +** other output channels. |
| 358 | +** |
| 359 | +** The default behavior, if neither of the above is defined is to |
| 360 | +** use O_U8TEXT when writing to the Windows console (or anything |
| 361 | +** else for which _isatty() returns true) and to use O_BINARY or O_TEXT |
| 362 | +** for all other output channels. |
| 369 | 363 | */ |
| 370 | 364 | #if defined(SQLITE_U8TEXT_ONLY) |
| 371 | 365 | # define UseWtextForOutput(fd) 1 |
| 372 | 366 | # define UseWtextForInput(fd) 1 |
| 373 | 367 | # define IsConsole(fd) _isatty(_fileno(fd)) |
| | @@ -378,10 +372,35 @@ |
| 378 | 372 | #else |
| 379 | 373 | # define UseWtextForOutput(fd) _isatty(_fileno(fd)) |
| 380 | 374 | # define UseWtextForInput(fd) _isatty(_fileno(fd)) |
| 381 | 375 | # define IsConsole(fd) 1 |
| 382 | 376 | #endif |
| 377 | + |
| 378 | +/* |
| 379 | +** Global variables determine if simulated O_BINARY mode is to be |
| 380 | +** used for stdout or other, respectively. Simulated O_BINARY mode |
| 381 | +** means the mode is usually O_BINARY, but switches to O_U8TEXT for |
| 382 | +** unicode characters U+0080 or greater (any character that has a |
| 383 | +** multi-byte representation in UTF-8). This is the only way we |
| 384 | +** have found to render Unicode characters on a Windows console while |
| 385 | +** at the same time avoiding undesirable \n to \r\n translation. |
| 386 | +*/ |
| 387 | +static int simBinaryStdout = 0; |
| 388 | +static int simBinaryOther = 0; |
| 389 | + |
| 390 | + |
| 391 | +/* |
| 392 | +** Determine if simulated binary mode should be used for output to fd |
| 393 | +*/ |
| 394 | +static int UseBinaryWText(FILE *fd){ |
| 395 | + if( fd==stdout || fd==stderr ){ |
| 396 | + return simBinaryStdout; |
| 397 | + }else{ |
| 398 | + return simBinaryOther; |
| 399 | + } |
| 400 | +} |
| 401 | + |
| 383 | 402 | |
| 384 | 403 | /* |
| 385 | 404 | ** Work-alike for the fopen() routine from the standard C library. |
| 386 | 405 | */ |
| 387 | 406 | FILE *sqlite3_fopen(const char *zFilename, const char *zMode){ |
| | @@ -400,10 +419,11 @@ |
| 400 | 419 | b2[sz2] = 0; |
| 401 | 420 | fp = _wfopen(b1, b2); |
| 402 | 421 | } |
| 403 | 422 | free(b1); |
| 404 | 423 | free(b2); |
| 424 | + simBinaryOther = 0; |
| 405 | 425 | return fp; |
| 406 | 426 | } |
| 407 | 427 | |
| 408 | 428 | |
| 409 | 429 | /* |
| | @@ -454,32 +474,72 @@ |
| 454 | 474 | /* Reading from a file or other input source, just read bytes without |
| 455 | 475 | ** any translation. */ |
| 456 | 476 | return fgets(buf, sz, in); |
| 457 | 477 | } |
| 458 | 478 | } |
| 479 | + |
| 480 | +/* |
| 481 | +** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and |
| 482 | +** greater, switch to O_U8TEXT. |
| 483 | +*/ |
| 484 | +static void piecemealOutput(wchar_t *b1, int sz, FILE *out){ |
| 485 | + int i; |
| 486 | + wchar_t c; |
| 487 | + while( sz>0 ){ |
| 488 | + for(i=0; i<sz && b1[i]>=0x80; i++){} |
| 489 | + if( i>0 ){ |
| 490 | + c = b1[i]; |
| 491 | + b1[i] = 0; |
| 492 | + fflush(out); |
| 493 | + _setmode(_fileno(out), _O_U8TEXT); |
| 494 | + fputws(b1, out); |
| 495 | + fflush(out); |
| 496 | + b1 += i; |
| 497 | + b1[0] = c; |
| 498 | + sz -= i; |
| 499 | + }else{ |
| 500 | + fflush(out); |
| 501 | + _setmode(_fileno(out), _O_TEXT); |
| 502 | + _setmode(_fileno(out), _O_BINARY); |
| 503 | + fwrite(&b1[0], 1, 1, out); |
| 504 | + for(i=1; i<sz && b1[i]<0x80; i++){ |
| 505 | + fwrite(&b1[i], 1, 1, out); |
| 506 | + } |
| 507 | + fflush(out); |
| 508 | + _setmode(_fileno(out), _O_U8TEXT); |
| 509 | + b1 += i; |
| 510 | + sz -= i; |
| 511 | + } |
| 512 | + } |
| 513 | +} |
| 459 | 514 | |
| 460 | 515 | /* |
| 461 | 516 | ** Work-alike for fputs() from the standard C library. |
| 462 | 517 | */ |
| 463 | 518 | int sqlite3_fputs(const char *z, FILE *out){ |
| 464 | | - if( UseWtextForOutput(out) ){ |
| 519 | + if( !UseWtextForOutput(out) ){ |
| 520 | + /* Writing to a file or other destination, just write bytes without |
| 521 | + ** any translation. */ |
| 522 | + return fputs(z, out); |
| 523 | + }else{ |
| 465 | 524 | /* When writing to the command-prompt in Windows, it is necessary |
| 466 | | - ** to use _O_WTEXT input mode and write UTF-16 characters. |
| 525 | + ** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead |
| 526 | + ** use O_U8TEXT for everything in text mode. |
| 467 | 527 | */ |
| 468 | 528 | int sz = (int)strlen(z); |
| 469 | 529 | wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) ); |
| 470 | 530 | if( b1==0 ) return 0; |
| 471 | 531 | sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz); |
| 472 | 532 | b1[sz] = 0; |
| 473 | 533 | _setmode(_fileno(out), _O_U8TEXT); |
| 474 | | - fputws(b1, out); |
| 534 | + if( UseBinaryWText(out) ){ |
| 535 | + piecemealOutput(b1, sz, out); |
| 536 | + }else{ |
| 537 | + fputws(b1, out); |
| 538 | + } |
| 475 | 539 | sqlite3_free(b1); |
| 476 | 540 | return 0; |
| 477 | | - }else{ |
| 478 | | - /* Writing to a file or other destination, just write bytes without |
| 479 | | - ** any translation. */ |
| 480 | | - return fputs(z, out); |
| 481 | 541 | } |
| 482 | 542 | } |
| 483 | 543 | |
| 484 | 544 | |
| 485 | 545 | /* |
| | @@ -517,10 +577,14 @@ |
| 517 | 577 | */ |
| 518 | 578 | void sqlite3_fsetmode(FILE *fp, int mode){ |
| 519 | 579 | if( !UseWtextForOutput(fp) ){ |
| 520 | 580 | fflush(fp); |
| 521 | 581 | _setmode(_fileno(fp), mode); |
| 582 | + }else if( fp==stdout || fp==stderr ){ |
| 583 | + simBinaryStdout = (mode==_O_BINARY); |
| 584 | + }else{ |
| 585 | + simBinaryOther = (mode==_O_BINARY); |
| 522 | 586 | } |
| 523 | 587 | } |
| 524 | 588 | |
| 525 | 589 | #endif /* defined(_WIN32) */ |
| 526 | 590 | |
| | @@ -6766,50 +6830,52 @@ |
| 6766 | 6830 | aIdx[4] = i; |
| 6767 | 6831 | idxNum |= 0x40; |
| 6768 | 6832 | } |
| 6769 | 6833 | continue; |
| 6770 | 6834 | } |
| 6771 | | - if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){ |
| 6772 | | - switch( op ){ |
| 6773 | | - case SQLITE_INDEX_CONSTRAINT_EQ: |
| 6774 | | - case SQLITE_INDEX_CONSTRAINT_IS: { |
| 6775 | | - idxNum |= 0x0080; |
| 6776 | | - idxNum &= ~0x3300; |
| 6777 | | - aIdx[5] = i; |
| 6778 | | - aIdx[6] = -1; |
| 6779 | | - bStartSeen = 1; |
| 6780 | | - break; |
| 6781 | | - } |
| 6782 | | - case SQLITE_INDEX_CONSTRAINT_GE: { |
| 6783 | | - if( idxNum & 0x0080 ) break; |
| 6784 | | - idxNum |= 0x0100; |
| 6785 | | - idxNum &= ~0x0200; |
| 6786 | | - aIdx[5] = i; |
| 6787 | | - bStartSeen = 1; |
| 6788 | | - break; |
| 6789 | | - } |
| 6790 | | - case SQLITE_INDEX_CONSTRAINT_GT: { |
| 6791 | | - if( idxNum & 0x0080 ) break; |
| 6792 | | - idxNum |= 0x0200; |
| 6793 | | - idxNum &= ~0x0100; |
| 6794 | | - aIdx[5] = i; |
| 6795 | | - bStartSeen = 1; |
| 6796 | | - break; |
| 6797 | | - } |
| 6798 | | - case SQLITE_INDEX_CONSTRAINT_LE: { |
| 6799 | | - if( idxNum & 0x0080 ) break; |
| 6800 | | - idxNum |= 0x1000; |
| 6801 | | - idxNum &= ~0x2000; |
| 6802 | | - aIdx[6] = i; |
| 6803 | | - break; |
| 6804 | | - } |
| 6805 | | - case SQLITE_INDEX_CONSTRAINT_LT: { |
| 6806 | | - if( idxNum & 0x0080 ) break; |
| 6807 | | - idxNum |= 0x2000; |
| 6808 | | - idxNum &= ~0x1000; |
| 6809 | | - aIdx[6] = i; |
| 6810 | | - break; |
| 6835 | + if( pConstraint->iColumn<SERIES_COLUMN_START ){ |
| 6836 | + if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){ |
| 6837 | + switch( op ){ |
| 6838 | + case SQLITE_INDEX_CONSTRAINT_EQ: |
| 6839 | + case SQLITE_INDEX_CONSTRAINT_IS: { |
| 6840 | + idxNum |= 0x0080; |
| 6841 | + idxNum &= ~0x3300; |
| 6842 | + aIdx[5] = i; |
| 6843 | + aIdx[6] = -1; |
| 6844 | + bStartSeen = 1; |
| 6845 | + break; |
| 6846 | + } |
| 6847 | + case SQLITE_INDEX_CONSTRAINT_GE: { |
| 6848 | + if( idxNum & 0x0080 ) break; |
| 6849 | + idxNum |= 0x0100; |
| 6850 | + idxNum &= ~0x0200; |
| 6851 | + aIdx[5] = i; |
| 6852 | + bStartSeen = 1; |
| 6853 | + break; |
| 6854 | + } |
| 6855 | + case SQLITE_INDEX_CONSTRAINT_GT: { |
| 6856 | + if( idxNum & 0x0080 ) break; |
| 6857 | + idxNum |= 0x0200; |
| 6858 | + idxNum &= ~0x0100; |
| 6859 | + aIdx[5] = i; |
| 6860 | + bStartSeen = 1; |
| 6861 | + break; |
| 6862 | + } |
| 6863 | + case SQLITE_INDEX_CONSTRAINT_LE: { |
| 6864 | + if( idxNum & 0x0080 ) break; |
| 6865 | + idxNum |= 0x1000; |
| 6866 | + idxNum &= ~0x2000; |
| 6867 | + aIdx[6] = i; |
| 6868 | + break; |
| 6869 | + } |
| 6870 | + case SQLITE_INDEX_CONSTRAINT_LT: { |
| 6871 | + if( idxNum & 0x0080 ) break; |
| 6872 | + idxNum |= 0x2000; |
| 6873 | + idxNum &= ~0x1000; |
| 6874 | + aIdx[6] = i; |
| 6875 | + break; |
| 6876 | + } |
| 6811 | 6877 | } |
| 6812 | 6878 | } |
| 6813 | 6879 | continue; |
| 6814 | 6880 | } |
| 6815 | 6881 | iCol = pConstraint->iColumn - SERIES_COLUMN_START; |
| | @@ -21202,10 +21268,11 @@ |
| 21202 | 21268 | u8 nEqpLevel; /* Depth of the EQP output graph */ |
| 21203 | 21269 | u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ |
| 21204 | 21270 | u8 bSafeMode; /* True to prohibit unsafe operations */ |
| 21205 | 21271 | u8 bSafeModePersist; /* The long-term value of bSafeMode */ |
| 21206 | 21272 | u8 eRestoreState; /* See comments above doAutoDetectRestore() */ |
| 21273 | + u8 crnlMode; /* Do NL-to-CRLF translations when enabled (maybe) */ |
| 21207 | 21274 | ColModeOpts cmOpts; /* Option values affecting columnar mode output */ |
| 21208 | 21275 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 21209 | 21276 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 21210 | 21277 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 21211 | 21278 | int outCount; /* Revert to stdout when reaching zero */ |
| | @@ -21382,17 +21449,11 @@ |
| 21382 | 21449 | #define SEP_Column "|" |
| 21383 | 21450 | #define SEP_Row "\n" |
| 21384 | 21451 | #define SEP_Tab "\t" |
| 21385 | 21452 | #define SEP_Space " " |
| 21386 | 21453 | #define SEP_Comma "," |
| 21387 | | -#ifdef SQLITE_U8TEXT_ONLY |
| 21388 | | - /* With the SQLITE_U8TEXT_ONLY option, the output will always be in |
| 21389 | | - ** text mode. The \r will be inserted automatically. */ |
| 21390 | | -# define SEP_CrLf "\n" |
| 21391 | | -#else |
| 21392 | | -# define SEP_CrLf "\r\n" |
| 21393 | | -#endif |
| 21454 | +#define SEP_CrLf "\n" /* Use ".crnl on" to get \r\n line endings */ |
| 21394 | 21455 | #define SEP_Unit "\x1F" |
| 21395 | 21456 | #define SEP_Record "\x1E" |
| 21396 | 21457 | |
| 21397 | 21458 | /* |
| 21398 | 21459 | ** Limit input nesting via .read or any other input redirect. |
| | @@ -21604,10 +21665,23 @@ |
| 21604 | 21665 | p->mode = p->modePrior; |
| 21605 | 21666 | p->shellFlgs = p->priorShFlgs; |
| 21606 | 21667 | memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); |
| 21607 | 21668 | memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); |
| 21608 | 21669 | } |
| 21670 | + |
| 21671 | +/* |
| 21672 | +** Set output mode to text or binary for Windows. |
| 21673 | +*/ |
| 21674 | +static void setCrnlMode(ShellState *p){ |
| 21675 | +#ifdef _WIN32 |
| 21676 | + if( p->crnlMode ){ |
| 21677 | + sqlite3_fsetmode(p->out, _O_TEXT); |
| 21678 | + }else{ |
| 21679 | + sqlite3_fsetmode(p->out, _O_BINARY); |
| 21680 | + } |
| 21681 | +#endif |
| 21682 | +} |
| 21609 | 21683 | |
| 21610 | 21684 | /* |
| 21611 | 21685 | ** Output the given string as a hex-encoded blob (eg. X'1234' ) |
| 21612 | 21686 | */ |
| 21613 | 21687 | static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ |
| | @@ -21655,13 +21729,14 @@ |
| 21655 | 21729 | /* |
| 21656 | 21730 | ** Output the given string as a quoted string using SQL quoting conventions. |
| 21657 | 21731 | ** |
| 21658 | 21732 | ** See also: output_quoted_escaped_string() |
| 21659 | 21733 | */ |
| 21660 | | -static void output_quoted_string(FILE *out, const char *z){ |
| 21734 | +static void output_quoted_string(ShellState *p, const char *z){ |
| 21661 | 21735 | int i; |
| 21662 | 21736 | char c; |
| 21737 | + FILE *out = p->out; |
| 21663 | 21738 | sqlite3_fsetmode(out, _O_BINARY); |
| 21664 | 21739 | if( z==0 ) return; |
| 21665 | 21740 | for(i=0; (c = z[i])!=0 && c!='\''; i++){} |
| 21666 | 21741 | if( c==0 ){ |
| 21667 | 21742 | sqlite3_fprintf(out, "'%s'",z); |
| | @@ -21683,11 +21758,11 @@ |
| 21683 | 21758 | } |
| 21684 | 21759 | z++; |
| 21685 | 21760 | } |
| 21686 | 21761 | sqlite3_fputs("'", out); |
| 21687 | 21762 | } |
| 21688 | | - sqlite3_fsetmode(out, _O_TEXT); |
| 21763 | + setCrnlMode(p); |
| 21689 | 21764 | } |
| 21690 | 21765 | |
| 21691 | 21766 | /* |
| 21692 | 21767 | ** Output the given string as a quoted string using SQL quoting conventions. |
| 21693 | 21768 | ** Additionallly , escape the "\n" and "\r" characters so that they do not |
| | @@ -21695,13 +21770,14 @@ |
| 21695 | 21770 | ** systems. |
| 21696 | 21771 | ** |
| 21697 | 21772 | ** This is like output_quoted_string() but with the addition of the \r\n |
| 21698 | 21773 | ** escape mechanism. |
| 21699 | 21774 | */ |
| 21700 | | -static void output_quoted_escaped_string(FILE *out, const char *z){ |
| 21775 | +static void output_quoted_escaped_string(ShellState *p, const char *z){ |
| 21701 | 21776 | int i; |
| 21702 | 21777 | char c; |
| 21778 | + FILE *out = p->out; |
| 21703 | 21779 | sqlite3_fsetmode(out, _O_BINARY); |
| 21704 | 21780 | for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} |
| 21705 | 21781 | if( c==0 ){ |
| 21706 | 21782 | sqlite3_fprintf(out, "'%s'",z); |
| 21707 | 21783 | }else{ |
| | @@ -21750,11 +21826,11 @@ |
| 21750 | 21826 | } |
| 21751 | 21827 | if( nNL ){ |
| 21752 | 21828 | sqlite3_fprintf(out, ",'%s',char(10))", zNL); |
| 21753 | 21829 | } |
| 21754 | 21830 | } |
| 21755 | | - sqlite3_fsetmode(stdout, _O_TEXT); |
| 21831 | + setCrnlMode(p); |
| 21756 | 21832 | } |
| 21757 | 21833 | |
| 21758 | 21834 | /* |
| 21759 | 21835 | ** Find earliest of chars within s specified in zAny. |
| 21760 | 21836 | ** With ns == ~0, is like strpbrk(s,zAny) and s must be 0-terminated. |
| | @@ -22539,19 +22615,27 @@ |
| 22539 | 22615 | sqlite3_fsetmode(p->out, _O_BINARY); |
| 22540 | 22616 | if( p->cnt++==0 && p->showHeader ){ |
| 22541 | 22617 | for(i=0; i<nArg; i++){ |
| 22542 | 22618 | output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
| 22543 | 22619 | } |
| 22544 | | - sqlite3_fputs(p->rowSeparator, p->out); |
| 22620 | + if( p->crnlMode && cli_strcmp(p->rowSeparator,SEP_CrLf)==0 ){ |
| 22621 | + sqlite3_fputs("\r\n", p->out); |
| 22622 | + }else{ |
| 22623 | + sqlite3_fputs(p->rowSeparator, p->out); |
| 22624 | + } |
| 22545 | 22625 | } |
| 22546 | 22626 | if( nArg>0 ){ |
| 22547 | 22627 | for(i=0; i<nArg; i++){ |
| 22548 | 22628 | output_csv(p, azArg[i], i<nArg-1); |
| 22549 | 22629 | } |
| 22550 | | - sqlite3_fputs(p->rowSeparator, p->out); |
| 22630 | + if( p->crnlMode && cli_strcmp(p->rowSeparator,SEP_CrLf)==0 ){ |
| 22631 | + sqlite3_fputs("\r\n", p->out); |
| 22632 | + }else{ |
| 22633 | + sqlite3_fputs(p->rowSeparator, p->out); |
| 22634 | + } |
| 22551 | 22635 | } |
| 22552 | | - sqlite3_fsetmode(p->out, _O_TEXT); |
| 22636 | + setCrnlMode(p); |
| 22553 | 22637 | break; |
| 22554 | 22638 | } |
| 22555 | 22639 | case MODE_Insert: { |
| 22556 | 22640 | if( azArg==0 ) break; |
| 22557 | 22641 | sqlite3_fprintf(p->out, "INSERT INTO %s",p->zDestTable); |
| | @@ -22575,13 +22659,13 @@ |
| 22575 | 22659 | sqlite3_fputs(i>0 ? "," : " VALUES(", p->out); |
| 22576 | 22660 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 22577 | 22661 | sqlite3_fputs("NULL", p->out); |
| 22578 | 22662 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| 22579 | 22663 | if( ShellHasFlag(p, SHFLG_Newlines) ){ |
| 22580 | | - output_quoted_string(p->out, azArg[i]); |
| 22664 | + output_quoted_string(p, azArg[i]); |
| 22581 | 22665 | }else{ |
| 22582 | | - output_quoted_escaped_string(p->out, azArg[i]); |
| 22666 | + output_quoted_escaped_string(p, azArg[i]); |
| 22583 | 22667 | } |
| 22584 | 22668 | }else if( aiType && aiType[i]==SQLITE_INTEGER ){ |
| 22585 | 22669 | sqlite3_fputs(azArg[i], p->out); |
| 22586 | 22670 | }else if( aiType && aiType[i]==SQLITE_FLOAT ){ |
| 22587 | 22671 | char z[50]; |
| | @@ -22606,13 +22690,13 @@ |
| 22606 | 22690 | int nBlob = sqlite3_column_bytes(p->pStmt, i); |
| 22607 | 22691 | output_hex_blob(p->out, pBlob, nBlob); |
| 22608 | 22692 | }else if( isNumber(azArg[i], 0) ){ |
| 22609 | 22693 | sqlite3_fputs(azArg[i], p->out); |
| 22610 | 22694 | }else if( ShellHasFlag(p, SHFLG_Newlines) ){ |
| 22611 | | - output_quoted_string(p->out, azArg[i]); |
| 22695 | + output_quoted_string(p, azArg[i]); |
| 22612 | 22696 | }else{ |
| 22613 | | - output_quoted_escaped_string(p->out, azArg[i]); |
| 22697 | + output_quoted_escaped_string(p, azArg[i]); |
| 22614 | 22698 | } |
| 22615 | 22699 | } |
| 22616 | 22700 | sqlite3_fputs(");\n", p->out); |
| 22617 | 22701 | break; |
| 22618 | 22702 | } |
| | @@ -22661,21 +22745,21 @@ |
| 22661 | 22745 | case MODE_Quote: { |
| 22662 | 22746 | if( azArg==0 ) break; |
| 22663 | 22747 | if( p->cnt==0 && p->showHeader ){ |
| 22664 | 22748 | for(i=0; i<nArg; i++){ |
| 22665 | 22749 | if( i>0 ) sqlite3_fputs(p->colSeparator, p->out); |
| 22666 | | - output_quoted_string(p->out, azCol[i]); |
| 22750 | + output_quoted_string(p, azCol[i]); |
| 22667 | 22751 | } |
| 22668 | 22752 | sqlite3_fputs(p->rowSeparator, p->out); |
| 22669 | 22753 | } |
| 22670 | 22754 | p->cnt++; |
| 22671 | 22755 | for(i=0; i<nArg; i++){ |
| 22672 | 22756 | if( i>0 ) sqlite3_fputs(p->colSeparator, p->out); |
| 22673 | 22757 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 22674 | 22758 | sqlite3_fputs("NULL", p->out); |
| 22675 | 22759 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| 22676 | | - output_quoted_string(p->out, azArg[i]); |
| 22760 | + output_quoted_string(p, azArg[i]); |
| 22677 | 22761 | }else if( aiType && aiType[i]==SQLITE_INTEGER ){ |
| 22678 | 22762 | sqlite3_fputs(azArg[i], p->out); |
| 22679 | 22763 | }else if( aiType && aiType[i]==SQLITE_FLOAT ){ |
| 22680 | 22764 | char z[50]; |
| 22681 | 22765 | double r = sqlite3_column_double(p->pStmt, i); |
| | @@ -22686,11 +22770,11 @@ |
| 22686 | 22770 | int nBlob = sqlite3_column_bytes(p->pStmt, i); |
| 22687 | 22771 | output_hex_blob(p->out, pBlob, nBlob); |
| 22688 | 22772 | }else if( isNumber(azArg[i], 0) ){ |
| 22689 | 22773 | sqlite3_fputs(azArg[i], p->out); |
| 22690 | 22774 | }else{ |
| 22691 | | - output_quoted_string(p->out, azArg[i]); |
| 22775 | + output_quoted_string(p, azArg[i]); |
| 22692 | 22776 | } |
| 22693 | 22777 | } |
| 22694 | 22778 | sqlite3_fputs(p->rowSeparator, p->out); |
| 22695 | 22779 | break; |
| 22696 | 22780 | } |
| | @@ -24690,14 +24774,11 @@ |
| 24690 | 24774 | #ifndef SQLITE_SHELL_FIDDLE |
| 24691 | 24775 | ".check GLOB Fail if output since .testcase does not match", |
| 24692 | 24776 | ".clone NEWDB Clone data into NEWDB from the existing database", |
| 24693 | 24777 | #endif |
| 24694 | 24778 | ".connection [close] [#] Open or close an auxiliary database connection", |
| 24695 | | -#if defined(_WIN32) && !defined(SQLITE_U8TEXT_ONLY) \ |
| 24696 | | - && !defined(SQLITE_U8TEXT_STDIO) |
| 24697 | | - ".crnl on|off Translate \\n to \\r\\n. Default ON", |
| 24698 | | -#endif /* _WIN32 && U8TEXT_ONLY && U8TEXT_STDIO */ |
| 24779 | + ".crnl on|off Translate \\n to \\r\\n sometimes. Default OFF", |
| 24699 | 24780 | ".databases List names and files of attached databases", |
| 24700 | 24781 | ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", |
| 24701 | 24782 | #if SQLITE_SHELL_HAVE_RECOVER |
| 24702 | 24783 | ".dbinfo ?DB? Show status information about the database", |
| 24703 | 24784 | #endif |
| | @@ -25692,20 +25773,20 @@ |
| 25692 | 25773 | /* |
| 25693 | 25774 | ** Try to open an output file. The names "stdout" and "stderr" are |
| 25694 | 25775 | ** recognized and do the right thing. NULL is returned if the output |
| 25695 | 25776 | ** filename is "off". |
| 25696 | 25777 | */ |
| 25697 | | -static FILE *output_file_open(const char *zFile, int bTextMode){ |
| 25778 | +static FILE *output_file_open(const char *zFile){ |
| 25698 | 25779 | FILE *f; |
| 25699 | 25780 | if( cli_strcmp(zFile,"stdout")==0 ){ |
| 25700 | 25781 | f = stdout; |
| 25701 | 25782 | }else if( cli_strcmp(zFile, "stderr")==0 ){ |
| 25702 | 25783 | f = stderr; |
| 25703 | 25784 | }else if( cli_strcmp(zFile, "off")==0 ){ |
| 25704 | 25785 | f = 0; |
| 25705 | 25786 | }else{ |
| 25706 | | - f = sqlite3_fopen(zFile, bTextMode ? "w" : "wb"); |
| 25787 | + f = sqlite3_fopen(zFile, "w"); |
| 25707 | 25788 | if( f==0 ){ |
| 25708 | 25789 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", zFile); |
| 25709 | 25790 | } |
| 25710 | 25791 | } |
| 25711 | 25792 | return f; |
| | @@ -26174,10 +26255,11 @@ |
| 26174 | 26255 | static void output_redir(ShellState *p, FILE *pfNew){ |
| 26175 | 26256 | if( p->out != stdout ){ |
| 26176 | 26257 | sqlite3_fputs("Output already redirected.\n", stderr); |
| 26177 | 26258 | }else{ |
| 26178 | 26259 | p->out = pfNew; |
| 26260 | + setCrnlMode(p); |
| 26179 | 26261 | if( p->mode==MODE_Www ){ |
| 26180 | 26262 | sqlite3_fputs( |
| 26181 | 26263 | "<!DOCTYPE html>\n" |
| 26182 | 26264 | "<HTML><BODY><PRE>\n", |
| 26183 | 26265 | p->out |
| | @@ -26229,10 +26311,11 @@ |
| 26229 | 26311 | } |
| 26230 | 26312 | #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ |
| 26231 | 26313 | } |
| 26232 | 26314 | p->outfile[0] = 0; |
| 26233 | 26315 | p->out = stdout; |
| 26316 | + setCrnlMode(p); |
| 26234 | 26317 | } |
| 26235 | 26318 | #else |
| 26236 | 26319 | # define output_redir(SS,pfO) |
| 26237 | 26320 | # define output_reset(SS) |
| 26238 | 26321 | #endif |
| | @@ -28183,11 +28266,11 @@ |
| 28183 | 28266 | } |
| 28184 | 28267 | }else |
| 28185 | 28268 | |
| 28186 | 28269 | /* Undocumented. Legacy only. See "crnl" below */ |
| 28187 | 28270 | if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){ |
| 28188 | | - eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n"); |
| 28271 | + eputz("The \".binary\" command is deprecated.\n"); |
| 28189 | 28272 | rc = 1; |
| 28190 | 28273 | }else |
| 28191 | 28274 | |
| 28192 | 28275 | /* The undocumented ".breakpoint" command causes a call to the no-op |
| 28193 | 28276 | ** routine named test_breakpoint(). |
| | @@ -28310,25 +28393,17 @@ |
| 28310 | 28393 | rc = 1; |
| 28311 | 28394 | } |
| 28312 | 28395 | }else |
| 28313 | 28396 | |
| 28314 | 28397 | if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){ |
| 28315 | | -#if !defined(_WIN32) || defined(SQLITE_U8TEXT_ONLY) \ |
| 28316 | | - || defined(SQLITE_U8TEXT_STDIO) |
| 28317 | | - sqlite3_fputs("The \".crnl\" command is disable in this build.\n", p->out); |
| 28318 | | -#else |
| 28319 | 28398 | if( nArg==2 ){ |
| 28320 | | - if( booleanValue(azArg[1]) ){ |
| 28321 | | - sqlite3_fsetmode(p->out, _O_TEXT); |
| 28322 | | - }else{ |
| 28323 | | - sqlite3_fsetmode(p->out, _O_BINARY); |
| 28324 | | - } |
| 28325 | | - }else{ |
| 28326 | | - eputz("Usage: .crnl on|off\n"); |
| 28327 | | - rc = 1; |
| 28328 | | - } |
| 28329 | | -#endif |
| 28399 | + p->crnlMode = booleanValue(azArg[1]); |
| 28400 | + setCrnlMode(p); |
| 28401 | + }else{ |
| 28402 | + sqlite3_fprintf(stderr, "crnl is currently %s\n", |
| 28403 | + p->crnlMode ? "ON" : "OFF"); |
| 28404 | + } |
| 28330 | 28405 | }else |
| 28331 | 28406 | |
| 28332 | 28407 | if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){ |
| 28333 | 28408 | char **azName = 0; |
| 28334 | 28409 | int nName = 0; |
| | @@ -29404,11 +29479,11 @@ |
| 29404 | 29479 | " than \"on\" or \"off\"\n"); |
| 29405 | 29480 | zFile = "off"; |
| 29406 | 29481 | } |
| 29407 | 29482 | output_file_close(p->pLog); |
| 29408 | 29483 | if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout"; |
| 29409 | | - p->pLog = output_file_open(zFile, 0); |
| 29484 | + p->pLog = output_file_open(zFile); |
| 29410 | 29485 | } |
| 29411 | 29486 | }else |
| 29412 | 29487 | |
| 29413 | 29488 | if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){ |
| 29414 | 29489 | const char *zMode = 0; |
| | @@ -29659,11 +29734,10 @@ |
| 29659 | 29734 | || cli_strncmp(azArg[0], "once", n)==0)) |
| 29660 | 29735 | || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0) |
| 29661 | 29736 | || (c=='w' && n==3 && cli_strcmp(azArg[0],"www")==0) |
| 29662 | 29737 | ){ |
| 29663 | 29738 | char *zFile = 0; |
| 29664 | | - int bTxtMode = 0; |
| 29665 | 29739 | int i; |
| 29666 | 29740 | int eMode = 0; |
| 29667 | 29741 | int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */ |
| 29668 | 29742 | int bPlain = 0; /* --plain option */ |
| 29669 | 29743 | static const char *zBomUtf8 = "\357\273\277"; |
| | @@ -29741,15 +29815,13 @@ |
| 29741 | 29815 | #endif |
| 29742 | 29816 | }else if( eMode=='w' ){ |
| 29743 | 29817 | /* web-browser mode. */ |
| 29744 | 29818 | newTempFile(p, "html"); |
| 29745 | 29819 | if( !bPlain ) p->mode = MODE_Www; |
| 29746 | | - bTxtMode = 1; |
| 29747 | 29820 | }else{ |
| 29748 | 29821 | /* text editor mode */ |
| 29749 | 29822 | newTempFile(p, "txt"); |
| 29750 | | - bTxtMode = 1; |
| 29751 | 29823 | } |
| 29752 | 29824 | sqlite3_free(zFile); |
| 29753 | 29825 | zFile = sqlite3_mprintf("%s", p->zTempFile); |
| 29754 | 29826 | } |
| 29755 | 29827 | #endif /* SQLITE_NOHAVE_SYSTEM */ |
| | @@ -29769,25 +29841,25 @@ |
| 29769 | 29841 | if( zBom ) sqlite3_fputs(zBom, pfPipe); |
| 29770 | 29842 | sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); |
| 29771 | 29843 | } |
| 29772 | 29844 | #endif |
| 29773 | 29845 | }else{ |
| 29774 | | - FILE *pfFile = output_file_open(zFile, bTxtMode); |
| 29846 | + FILE *pfFile = output_file_open(zFile); |
| 29775 | 29847 | if( pfFile==0 ){ |
| 29776 | 29848 | if( cli_strcmp(zFile,"off")!=0 ){ |
| 29777 | 29849 | sqlite3_fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile); |
| 29778 | 29850 | } |
| 29779 | 29851 | rc = 1; |
| 29780 | 29852 | } else { |
| 29781 | 29853 | output_redir(p, pfFile); |
| 29854 | + if( zBom ) sqlite3_fputs(zBom, pfFile); |
| 29782 | 29855 | if( bPlain && eMode=='w' ){ |
| 29783 | 29856 | sqlite3_fputs( |
| 29784 | 29857 | "<!DOCTYPE html>\n<BODY>\n<PLAINTEXT>\n", |
| 29785 | 29858 | pfFile |
| 29786 | 29859 | ); |
| 29787 | 29860 | } |
| 29788 | | - if( zBom ) sqlite3_fputs(zBom, pfFile); |
| 29789 | 29861 | sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); |
| 29790 | 29862 | } |
| 29791 | 29863 | } |
| 29792 | 29864 | sqlite3_free(zFile); |
| 29793 | 29865 | }else |
| | @@ -29980,11 +30052,10 @@ |
| 29980 | 30052 | } |
| 29981 | 30053 | if( azArg[1][0]=='|' ){ |
| 29982 | 30054 | #ifdef SQLITE_OMIT_POPEN |
| 29983 | 30055 | eputz("Error: pipes are not supported in this OS\n"); |
| 29984 | 30056 | rc = 1; |
| 29985 | | - p->out = stdout; |
| 29986 | 30057 | #else |
| 29987 | 30058 | p->in = sqlite3_popen(azArg[1]+1, "r"); |
| 29988 | 30059 | if( p->in==0 ){ |
| 29989 | 30060 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 29990 | 30061 | rc = 1; |
| | @@ -30967,11 +31038,11 @@ |
| 30967 | 31038 | |
| 30968 | 31039 | #ifndef SQLITE_SHELL_FIDDLE |
| 30969 | 31040 | /* Begin redirecting output to the file "testcase-out.txt" */ |
| 30970 | 31041 | if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){ |
| 30971 | 31042 | output_reset(p); |
| 30972 | | - p->out = output_file_open("testcase-out.txt", 0); |
| 31043 | + p->out = output_file_open("testcase-out.txt"); |
| 30973 | 31044 | if( p->out==0 ){ |
| 30974 | 31045 | eputz("Error: cannot open 'testcase-out.txt'\n"); |
| 30975 | 31046 | } |
| 30976 | 31047 | if( nArg>=2 ){ |
| 30977 | 31048 | sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); |
| | @@ -31471,11 +31542,11 @@ |
| 31471 | 31542 | rc = 1; |
| 31472 | 31543 | goto meta_command_exit; |
| 31473 | 31544 | } |
| 31474 | 31545 | }else{ |
| 31475 | 31546 | output_file_close(p->traceOut); |
| 31476 | | - p->traceOut = output_file_open(z, 0); |
| 31547 | + p->traceOut = output_file_open(z); |
| 31477 | 31548 | } |
| 31478 | 31549 | } |
| 31479 | 31550 | if( p->traceOut==0 ){ |
| 31480 | 31551 | sqlite3_trace_v2(p->db, 0, 0, 0); |
| 31481 | 31552 | }else{ |
| | @@ -32361,10 +32432,20 @@ |
| 32361 | 32432 | #endif |
| 32362 | 32433 | sqlite3_config(SQLITE_CONFIG_URI, 1); |
| 32363 | 32434 | sqlite3_config(SQLITE_CONFIG_MULTITHREAD); |
| 32364 | 32435 | sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); |
| 32365 | 32436 | sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); |
| 32437 | + |
| 32438 | + /* By default, come up in O_BINARY mode. That way, the default output is |
| 32439 | + ** the same for Windows and non-Windows systems. Use the ".crnl on" |
| 32440 | + ** command to change into O_TEXT mode to do automatic NL-to-CRLF |
| 32441 | + ** conversions on output for Windows. |
| 32442 | + ** |
| 32443 | + ** End-of-line marks on CVS output is CRLF when in .crnl is on and |
| 32444 | + ** NL when .crnl is off. |
| 32445 | + */ |
| 32446 | + data->crnlMode = 0; |
| 32366 | 32447 | } |
| 32367 | 32448 | |
| 32368 | 32449 | /* |
| 32369 | 32450 | ** Output text to the console in a font that attracts extra attention. |
| 32370 | 32451 | */ |
| 32371 | 32452 | |