/ Changes On Branch expShell
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch expShell Excluding Merge-Ins

This is equivalent to a diff from d3c00d6158 to 22827542a5

2015-05-21
02:07
When parsing the schema, ignore any SQL that does not begin with "CREATE". Cherrypick of [d3c00d61581c] with additional changes. (check-in: 09784f376b user: drh tags: branch-3.7.11)
2015-05-20
19:57
When parsing the schema, ignore any SQL that does not begin with "CREATE". Cherrypick of [d3c00d61581c]. (check-in: 0da229b81a user: dan tags: branch-3.8.6)
2015-05-04
19:13
In the command-line shell, and the ".binary" command and additional C-style backslash escapes. (check-in: 850c118666 user: drh tags: trunk)
2015-04-16
11:56
Use a heap instead of a bitmap for cell overlap and coverage testing of btree pages in PRAGMA integrity_check. (Closed-Leaf check-in: 5619c959bf user: drh tags: integrity-check-heap)
07:19
Ensure the sqlite3Select() routine always returns non-zero if an error has occurred. (check-in: b51028ed2f user: dan tags: trunk)
04:20
Merge updates from trunk. (Closed-Leaf check-in: 22827542a5 user: mistachkin tags: expShell)
03:24
Merge updates from trunk. Make OSTRACE changes work on Linux. (check-in: cd1542664e user: mistachkin tags: winTest)
00:26
When parsing the schema, ignore any SQL that does not begin with "CREATE". (check-in: d3c00d6158 user: drh tags: trunk)
2015-04-15
19:25
Fix a potential one-byte buffer overread in the command-line shell. (check-in: e018f4bf1f user: drh tags: trunk)
2015-04-07
21:18
Merge updates from trunk. (check-in: c458db41bb user: mistachkin tags: expShell)

Changes to src/shell.c.

   985    985         }
   986    986         setTextMode(p->out);
   987    987         break;
   988    988       }
   989    989       case MODE_Insert: {
   990    990         p->cnt++;
   991    991         if( azArg==0 ) break;
   992         -      fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
          992  +      fprintf(p->out,"INSERT INTO %s",p->zDestTable);
          993  +      if( p->showHeader ){
          994  +        fprintf(p->out,"(");
          995  +        for(i=0; i<nArg; i++){
          996  +          char *zSep = i>0 ? ",": "";
          997  +          fprintf(p->out, "%s%s", zSep, azCol[i]);
          998  +        }
          999  +        fprintf(p->out,")");
         1000  +      }
         1001  +      fprintf(p->out," VALUES(");
   993   1002         for(i=0; i<nArg; i++){
   994   1003           char *zSep = i>0 ? ",": "";
   995   1004           if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
   996   1005             fprintf(p->out,"%sNULL",zSep);
   997   1006           }else if( aiType && aiType[i]==SQLITE_TEXT ){
   998   1007             if( zSep[0] ) fprintf(p->out,"%s",zSep);
   999   1008             output_quoted_string(p->out, azArg[i]);
................................................................................
  1767   1776   
  1768   1777   /*
  1769   1778   ** Text of a help message
  1770   1779   */
  1771   1780   static char zHelp[] =
  1772   1781     ".backup ?DB? FILE      Backup DB (default \"main\") to FILE\n"
  1773   1782     ".bail on|off           Stop after hitting an error.  Default OFF\n"
         1783  +  ".binary on|off         Turn binary output on or off.  Default OFF\n"
  1774   1784     ".clone NEWDB           Clone data into NEWDB from the existing database\n"
  1775   1785     ".databases             List names and files of attached databases\n"
  1776   1786     ".dbinfo ?DB?           Show status information about the database\n"
  1777   1787     ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
  1778   1788     "                         If TABLE specified, only dump tables matching\n"
  1779   1789     "                         LIKE pattern TABLE.\n"
  1780   1790     ".echo on|off           Turn command echo on or off\n"
................................................................................
  1928   1938                               writefileFunc, 0, 0);
  1929   1939     }
  1930   1940   }
  1931   1941   
  1932   1942   /*
  1933   1943   ** Do C-language style dequoting.
  1934   1944   **
         1945  +**    \a    -> alarm
         1946  +**    \b    -> backspace
  1935   1947   **    \t    -> tab
  1936   1948   **    \n    -> newline
         1949  +**    \v    -> vertical tab
         1950  +**    \f    -> form feed
  1937   1951   **    \r    -> carriage return
         1952  +**    \s    -> space
  1938   1953   **    \"    -> "
  1939         -**    \NNN  -> ascii character NNN in octal
         1954  +**    \'    -> '
  1940   1955   **    \\    -> backslash
         1956  +**    \NNN  -> ascii character NNN in octal
  1941   1957   */
  1942   1958   static void resolve_backslashes(char *z){
  1943   1959     int i, j;
  1944   1960     char c;
  1945   1961     while( *z && *z!='\\' ) z++;
  1946   1962     for(i=j=0; (c = z[i])!=0; i++, j++){
  1947   1963       if( c=='\\' && z[i+1]!=0 ){
  1948   1964         c = z[++i];
  1949         -      if( c=='n' ){
  1950         -        c = '\n';
         1965  +      if( c=='a' ){
         1966  +        c = '\a';
         1967  +      }else if( c=='b' ){
         1968  +        c = '\b';
  1951   1969         }else if( c=='t' ){
  1952   1970           c = '\t';
         1971  +      }else if( c=='n' ){
         1972  +        c = '\n';
         1973  +      }else if( c=='v' ){
         1974  +        c = '\v';
         1975  +      }else if( c=='f' ){
         1976  +        c = '\f';
  1953   1977         }else if( c=='r' ){
  1954   1978           c = '\r';
         1979  +      }else if( c=='"' ){
         1980  +        c = '"';
         1981  +      }else if( c=='\'' ){
         1982  +        c = '\'';
  1955   1983         }else if( c=='\\' ){
  1956   1984           c = '\\';
  1957   1985         }else if( c>='0' && c<='7' ){
  1958   1986           c -= '0';
  1959   1987           if( z[i+1]>='0' && z[i+1]<='7' ){
  1960   1988             i++;
  1961   1989             c = (c<<3) + z[i] - '0';
................................................................................
  2680   2708       if( nArg==2 ){
  2681   2709         bail_on_error = booleanValue(azArg[1]);
  2682   2710       }else{
  2683   2711         fprintf(stderr, "Usage: .bail on|off\n");
  2684   2712         rc = 1;
  2685   2713       }
  2686   2714     }else
         2715  +
         2716  +  if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
         2717  +    if( nArg==2 ){
         2718  +      if( booleanValue(azArg[1]) ){
         2719  +        setBinaryMode(p->out);
         2720  +      }else{
         2721  +        setTextMode(p->out);
         2722  +      }
         2723  +    }else{
         2724  +      fprintf(stderr, "Usage: .binary on|off\n");
         2725  +      rc = 1;
         2726  +    }
         2727  +  }else
  2687   2728   
  2688   2729     /* The undocumented ".breakpoint" command causes a call to the no-op
  2689   2730     ** routine named test_breakpoint().
  2690   2731     */
  2691   2732     if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
  2692   2733       test_breakpoint();
  2693   2734     }else

Changes to test/shell1.test.

   734    734     db close
   735    735     forcedelete test.db
   736    736     sqlite3 db test.db
   737    737     db eval {
   738    738       PRAGMA encoding=UTF16;
   739    739       CREATE TABLE t1(x);
   740    740       INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f');
          741  +    CREATE TABLE t3(x,y);
          742  +    INSERT INTO t3 VALUES(1,null), (2,''), (3,1),
          743  +                         (4,2.25), (5,'hello'), (6,x'807f');
   741    744     }
   742    745     catchcmd test.db {.dump}
   743    746   } {0 {PRAGMA foreign_keys=OFF;
   744    747   BEGIN TRANSACTION;
   745    748   CREATE TABLE t1(x);
   746    749   INSERT INTO "t1" VALUES(NULL);
   747    750   INSERT INTO "t1" VALUES('');
   748    751   INSERT INTO "t1" VALUES(1);
   749    752   INSERT INTO "t1" VALUES(2.25);
   750    753   INSERT INTO "t1" VALUES('hello');
   751    754   INSERT INTO "t1" VALUES(X'807F');
          755  +CREATE TABLE t3(x,y);
          756  +INSERT INTO "t3" VALUES(1,NULL);
          757  +INSERT INTO "t3" VALUES(2,'');
          758  +INSERT INTO "t3" VALUES(3,1);
          759  +INSERT INTO "t3" VALUES(4,2.25);
          760  +INSERT INTO "t3" VALUES(5,'hello');
          761  +INSERT INTO "t3" VALUES(6,X'807F');
   752    762   COMMIT;}}
   753    763   
   754    764   # Test the output of ".mode insert"
   755    765   #
   756         -do_test shell1-4.2 {
          766  +do_test shell1-4.2.1 {
   757    767     catchcmd test.db ".mode insert t1\nselect * from t1;"
   758    768   } {0 {INSERT INTO t1 VALUES(NULL);
   759    769   INSERT INTO t1 VALUES('');
   760    770   INSERT INTO t1 VALUES(1);
   761    771   INSERT INTO t1 VALUES(2.25);
   762    772   INSERT INTO t1 VALUES('hello');
   763    773   INSERT INTO t1 VALUES(X'807f');}}
          774  +
          775  +# Test the output of ".mode insert" with headers
          776  +#
          777  +do_test shell1-4.2.2 {
          778  +  catchcmd test.db ".mode insert t1\n.headers on\nselect * from t1;"
          779  +} {0 {INSERT INTO t1(x) VALUES(NULL);
          780  +INSERT INTO t1(x) VALUES('');
          781  +INSERT INTO t1(x) VALUES(1);
          782  +INSERT INTO t1(x) VALUES(2.25);
          783  +INSERT INTO t1(x) VALUES('hello');
          784  +INSERT INTO t1(x) VALUES(X'807f');}}
          785  +
          786  +# Test the output of ".mode insert"
          787  +#
          788  +do_test shell1-4.2.3 {
          789  +  catchcmd test.db ".mode insert t3\nselect * from t3;"
          790  +} {0 {INSERT INTO t3 VALUES(1,NULL);
          791  +INSERT INTO t3 VALUES(2,'');
          792  +INSERT INTO t3 VALUES(3,1);
          793  +INSERT INTO t3 VALUES(4,2.25);
          794  +INSERT INTO t3 VALUES(5,'hello');
          795  +INSERT INTO t3 VALUES(6,X'807f');}}
          796  +
          797  +# Test the output of ".mode insert" with headers
          798  +#
          799  +do_test shell1-4.2.4 {
          800  +  catchcmd test.db ".mode insert t3\n.headers on\nselect * from t3;"
          801  +} {0 {INSERT INTO t3(x,y) VALUES(1,NULL);
          802  +INSERT INTO t3(x,y) VALUES(2,'');
          803  +INSERT INTO t3(x,y) VALUES(3,1);
          804  +INSERT INTO t3(x,y) VALUES(4,2.25);
          805  +INSERT INTO t3(x,y) VALUES(5,'hello');
          806  +INSERT INTO t3(x,y) VALUES(6,X'807f');}}
   764    807   
   765    808   # Test the output of ".mode tcl"
   766    809   #
   767    810   do_test shell1-4.3 {
   768    811     db close
   769    812     forcedelete test.db
   770    813     sqlite3 db test.db
................................................................................
   813    856   } {0 {"\""
   814    857   "["
   815    858   "]"
   816    859   "\\{"
   817    860   "\\}"
   818    861   ";"
   819    862   "$"} 7}
          863  +
          864  +# Test using arbitrary byte data with the shell via standard input/output.
          865  +#
          866  +do_test shell1-5.0 {
          867  +  #
          868  +  # NOTE: Skip NUL byte because it appears to be incompatible with command
          869  +  #       shell argument parsing.
          870  +  #
          871  +  for {set i 1} {$i < 256} {incr i} {
          872  +    #
          873  +    # NOTE: Due to how the Tcl [exec] command works (i.e. where it treats
          874  +    #       command channels opened for it as textual ones), the carriage
          875  +    #       return character (and on Windows, the end-of-file character)
          876  +    #       cannot be used here.
          877  +    #
          878  +    if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} {
          879  +      continue
          880  +    }
          881  +    set hex [format %02X $i]
          882  +    set char [subst \\x$hex]; set oldChar $char
          883  +    set escapes [list]
          884  +    if {$tcl_platform(platform)=="windows"} {
          885  +      #
          886  +      # NOTE: On Windows, we need to escape all the whitespace characters,
          887  +      #       the alarm (\a) character, and those with special meaning to
          888  +      #       the SQLite shell itself.
          889  +      #
          890  +      set escapes [list \
          891  +          \a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \
          892  +          " " "\" \"" \" \\\" ' \"'\" \\ \\\\]
          893  +    } else {
          894  +      #
          895  +      # NOTE: On Unix, we need to escape most of the whitespace characters
          896  +      #       and those with special meaning to the SQLite shell itself.
          897  +      #       The alarm (\a), backspace (\b), and carriage-return (\r)
          898  +      #       characters do not appear to require escaping on Unix.  For
          899  +      #       the alarm and backspace characters, this is probably due to
          900  +      #       differences in the command shell.  For the carriage-return,
          901  +      #       it is probably due to differences in how Tcl handles command
          902  +      #       channel end-of-line translations.
          903  +      #
          904  +      set escapes [list \
          905  +          \t \\t \n \\n \v \\v \f \\f \
          906  +          " " "\" \"" \" \\\" ' \"'\" \\ \\\\]
          907  +    }
          908  +    set char [string map $escapes $char]
          909  +    set x [catchcmdex test.db ".print $char\n"]
          910  +    set code [lindex $x 0]
          911  +    set res [lindex $x 1]
          912  +    if {$code ne "0"} {
          913  +      error "failed with error: $res"
          914  +    }
          915  +    if {$res ne "$oldChar\n"} {
          916  +      error "failed with byte $hex mismatch"
          917  +    }
          918  +  }
          919  +} {}
   820    920   
   821    921   finish_test

Changes to test/tester.tcl.

   661    661       }
   662    662     } else {
   663    663       puts " Omitted"
   664    664       omit_test $name "pattern mismatch" 0
   665    665     }
   666    666     flush stdout
   667    667   }
          668  +
          669  +proc dumpbytes {s} {
          670  +  set r ""
          671  +  for {set i 0} {$i < [string length $s]} {incr i} {
          672  +    if {$i > 0} {append r " "}
          673  +    append r [format %02X [scan [string index $s $i] %c]]
          674  +  }
          675  +  return $r
          676  +}
   668    677   
   669    678   proc catchcmd {db {cmd ""}} {
   670    679     global CLI
   671    680     set out [open cmds.txt w]
   672    681     puts $out $cmd
   673    682     close $out
   674    683     set line "exec $CLI $db < cmds.txt"
   675    684     set rc [catch { eval $line } msg]
   676    685     list $rc $msg
   677    686   }
          687  +
          688  +proc catchcmdex {db {cmd ""}} {
          689  +  global CLI
          690  +  set out [open cmds.txt w]
          691  +  fconfigure $out -encoding binary -translation binary
          692  +  puts -nonewline $out $cmd
          693  +  close $out
          694  +  set line "exec -keepnewline -- $CLI $db < cmds.txt"
          695  +  set chans [list stdin stdout stderr]
          696  +  foreach chan $chans {
          697  +    catch {
          698  +      set modes($chan) [fconfigure $chan]
          699  +      fconfigure $chan -encoding binary -translation binary -buffering none
          700  +    }
          701  +  }
          702  +  set rc [catch { eval $line } msg]
          703  +  foreach chan $chans {
          704  +    catch {
          705  +      eval fconfigure [list $chan] $modes($chan)
          706  +    }
          707  +  }
          708  +  # puts [dumpbytes $msg]
          709  +  list $rc $msg
          710  +}
   678    711   
   679    712   proc filepath_normalize {p} {
   680    713     # test cases should be written to assume "unix"-like file paths
   681    714     if {$::tcl_platform(platform)!="unix"} {
   682    715       # lreverse*2 as a hack to remove any unneeded {} after the string map
   683    716       lreverse [lreverse [string map {\\ /} [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]]]
   684    717     } {