/ Check-in [5d2e72e4]
Login

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

Overview
Comment::-) (CVS 66)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5d2e72e4bd5e218133190b8b1ebe52f48e2d7140
User & Date: drh 2000-06-07 01:27:48
Context
2000-06-07
01:33
:-) (CVS 67) check-in: 8bff1bee user: drh tags: trunk
01:27
:-) (CVS 66) check-in: 5d2e72e4 user: drh tags: trunk
00:12
:-) (CVS 65) check-in: 80ee166e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/shell.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
118
119
120
121
122
123
124

125
126
127
128

129
130
131
132
133
134
135
...
196
197
198
199
200
201
202






203






204
205
206
207
208
209
210
211
...
221
222
223
224
225
226
227

























228
229
230
231
232

233
234
235
236
237
238
239
...
274
275
276
277
278
279
280























281
282
283
284
285
286
287
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.9 2000/06/07 00:12:25 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................

/*
** An pointer to an instance of this structure is passed from
** the main program to the callback.  This is used to communicate
** state and mode information.
*/
struct callback_data {

  int cnt;           /* Number of records displayed so far */
  FILE *out;         /* Write results here */
  int mode;          /* An output mode setting */
  int showHeader;    /* True to show column names in List or Column mode */

  char separator[20];/* Separator character for MODE_List */
  int colWidth[30];  /* Width of each column when in column mode */
};

/*
** These are the allowed modes.
*/
................................................................................
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
        }
      }
      for(i=0; i<nArg; i++){






        fprintf(p->out,"%s%s",azArg[i] ? azArg[i] : "",






             i==nArg-1 ? "\n" : p->separator);
      }
      break;
    }
    case MODE_Html: {
      if( p->cnt++==0 && p->showHeader ){
        fprintf(p->out,"<TR>");
        for(i=0; i<nArg; i++){
................................................................................
        fprintf(p->out,"</TD>\n");
      }
      break;
    }
  }      
  return 0;
}


























/*
** Text of a help message
*/
static char zHelp[] = 

  ".exit                  Exit this program\n"
  ".explain               Set output mode suitable for EXPLAIN\n"
  ".header ON|OFF         Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".indices TABLE         Show names of all indices on TABLE\n"
  ".mode MODE             Set mode to one of \"line\", \"column\", "
                                      "\"list\", or \"html\"\n"
................................................................................
  }

  /* Process the input line.
  */
  if( nArg==0 ) return;
  n = strlen(azArg[0]);
  c = azArg[0][0];
























  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    exit(0);
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    p->mode = MODE_Column;
................................................................................
    struct callback_data data;
    char *zErrMsg = 0;
    char zSql[1000];
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    sprintf(zSql, "SELECT name FROM sqlite_master "
                  "WHERE type='index' AND tbl_name LIKE '%.00s' "
                  "ORDER BY name", azArg[1]);
    sqlite_exec(db, zSql, callback, &data, &zErrMsg);
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else
................................................................................
      return 1;
    }
  }
  if( argc!=2 && argc!=3 ){
    fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
    exit(1);
  }
  db = sqlite_open(argv[1], 0666, &zErrMsg);
  if( db==0 ){
    if( zErrMsg ){
      fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1], zErrMsg);
    }else{
      fprintf(stderr,"Unable to open database %s\n", argv[1]);
    }
    exit(1);







|







 







>




>







 







>
>
>
>
>
>
|
>
>
>
>
>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.10 2000/06/07 01:27:48 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................

/*
** An pointer to an instance of this structure is passed from
** the main program to the callback.  This is used to communicate
** state and mode information.
*/
struct callback_data {
  sqlite *db;        /* The database */
  int cnt;           /* Number of records displayed so far */
  FILE *out;         /* Write results here */
  int mode;          /* An output mode setting */
  int showHeader;    /* True to show column names in List or Column mode */
  int escape;        /* Escape this character when in MODE_List */
  char separator[20];/* Separator character for MODE_List */
  int colWidth[30];  /* Width of each column when in column mode */
};

/*
** These are the allowed modes.
*/
................................................................................
    case MODE_List: {
      if( p->cnt++==0 && p->showHeader ){
        for(i=0; i<nArg; i++){
          fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
        }
      }
      for(i=0; i<nArg; i++){
        char *z = azArg[i];
        if( z==0 ) z = "";
        while( *z ){
          int j;
          for(j=0; z[j] && z[j]!=p->escape && z[j]!='\\'; j++){}
          if( j>0 ){
            fprintf(p->out, "%.*s", j, z);
          }
          if( z[j] ){
            fprintf(p->out, "\\%c", z[j]);
            z = &z[j+1];
          }
        }
        fprintf(p->out, "%s", i==nArg-1 ? "\n" : p->separator);
      }
      break;
    }
    case MODE_Html: {
      if( p->cnt++==0 && p->showHeader ){
        fprintf(p->out,"<TR>");
        for(i=0; i<nArg; i++){
................................................................................
        fprintf(p->out,"</TD>\n");
      }
      break;
    }
  }      
  return 0;
}

/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  struct callback_data *pData = (struct callback_data *)pArg;
  if( nArg!=3 ) return 1;
  fprintf(pData->out, "%s;\n", azArg[2]);
  if( strcmp(azArg[1],"table")==0 ){
    struct callback_data d2;
    char zSql[1000];
    d2 = *pData;
    d2.mode = MODE_List;
    strcpy(d2.separator,"\t");
    fprintf(pData->out, "COPY '%s' FROM STDIN;\n", azArg[0]);
    sprintf(zSql, "SELECT * FROM '%s'", azArg[0]);
    sqlite_exec(pData->db, zSql, callback, &d2, 0);
    fprintf(pData->out, "\\.\n");
  }
  fprintf(pData->out, "VACUUM '%s';\n", azArg[2]);
  return 0;
}

/*
** Text of a help message
*/
static char zHelp[] = 
  ".dump ?TABLE? ...      Dump the database in an text format\n"
  ".exit                  Exit this program\n"
  ".explain               Set output mode suitable for EXPLAIN\n"
  ".header ON|OFF         Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".indices TABLE         Show names of all indices on TABLE\n"
  ".mode MODE             Set mode to one of \"line\", \"column\", "
                                      "\"list\", or \"html\"\n"
................................................................................
  }

  /* Process the input line.
  */
  if( nArg==0 ) return;
  n = strlen(azArg[0]);
  c = azArg[0][0];
 
  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
    char *zErrMsg = 0;
    char zSql[1000];
    if( nArg==1 ){
      sprintf(zSql, "SELECT name, type, sql FROM sqlite_master "
                    "ORDER BY tbl_name, type DESC, name");
      sqlite_exec(db, zSql, dump_callback, p, &zErrMsg);
    }else{
      int i;
      for(i=1; i<nArg && zErrMsg==0; i++){
        sprintf(zSql, "SELECT name, type, sql FROM sqlite_master "
                      "WHERE tbl_name LIKE '%.800s'"
                      "ORDER BY type DESC, name", azArg[i]);
        sqlite_exec(db, zSql, dump_callback, p, &zErrMsg);
        
      }
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else

  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    exit(0);
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    p->mode = MODE_Column;
................................................................................
    struct callback_data data;
    char *zErrMsg = 0;
    char zSql[1000];
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    sprintf(zSql, "SELECT name FROM sqlite_master "
                  "WHERE type='index' AND tbl_name LIKE '%.800s' "
                  "ORDER BY name", azArg[1]);
    sqlite_exec(db, zSql, callback, &data, &zErrMsg);
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else
................................................................................
      return 1;
    }
  }
  if( argc!=2 && argc!=3 ){
    fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
    exit(1);
  }
  data.db = db = sqlite_open(argv[1], 0666, &zErrMsg);
  if( db==0 ){
    if( zErrMsg ){
      fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1], zErrMsg);
    }else{
      fprintf(stderr,"Unable to open database %s\n", argv[1]);
    }
    exit(1);

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
....
2613
2614
2615
2616
2617
2618
2619
2620
2621










2622
2623
2624
2625



2626
2627
2628
2629
2630
2631
2632
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.25 2000/06/07 00:12:25 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
          goto fileread_jump;
        }
        zDelim = pOp->p3;
        if( zDelim==0 ) zDelim = "\t";
        c = zDelim[0];
        nDelim = strlen(zDelim);
        p->azField[0] = z;
        for(i=1; *z!=0 && i<nField; i++){
          while( *z && (*z!=c || strncmp(z,zDelim,nDelim)) ){ z++; }










          if( *z ){
            *z = 0;
            z += nDelim;
            p->azField[i] = z;



          }
        }
        while( i<nField ){
          p->azField[i++] = "";
        }
        break;








|







 







|
|
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
....
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.26 2000/06/07 01:27:49 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
          goto fileread_jump;
        }
        zDelim = pOp->p3;
        if( zDelim==0 ) zDelim = "\t";
        c = zDelim[0];
        nDelim = strlen(zDelim);
        p->azField[0] = z;
        for(i=1; *z!=0 && i<=nField; i++){
          int from, to;
          from = to = 0;
          while( z[from] ){
            if( z[from]=='\\' && z[from+1]!=0 ){
              z[to++] = z[from+1];
              from += 2;
              continue;
            }
            if( z[from]==c && strncmp(&z[from],zDelim,nDelim)==0 ) break;
            z[to++] = z[from++];
          }
          if( z[from] ){
            z[to] = 0;
            z += from + nDelim;
            if( i<nField ) p->azField[i] = z;
          }else{
            z[to] = 0;
            z = "";
          }
        }
        while( i<nField ){
          p->azField[i++] = "";
        }
        break;

Changes to test/copy.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
...
131
132
133
134
135
136
137














138
139
140
141
142
143
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.4 2000/06/05 18:54:47 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]
................................................................................
  execsql {DELETE FROM test1}
  execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS '|'}
  execsql {SELECT * FROM test1 ORDER BY one}
} {{11 } { 22 } { 33} {22 } { 33 } { 11}}

# Try copying into a table that has one or more indices.
#

execsql {DELETE FROM test1}
execsql {CREATE INDEX index1 ON test1(one)}
execsql {CREATE INDEX index2 ON test1(two)}
execsql {CREATE INDEX index3 ON test1(three)}
do_test copy-1.8 {
  execsql {COPY test1 from 'data1.txt'}
  execsql {SELECT * FROM test1 WHERE one=11}
} {11 22 33}
do_test copy-1.8b {
  execsql {SELECT * FROM test1 WHERE one=22}
} {22 33 11}
do_test copy-1.8c {
................................................................................
  execsql {CREATE TABLE test2(a int, x text)}
  set f [open data21.txt w]
  puts $f "123\t$x"
  close $f
  execsql {COPY test2 FROM 'data21.txt'}
  execsql {SELECT x from test2}
} $x















# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data21.txt

finish_test







|







 







>
|
|
|
|
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>






19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.5 2000/06/07 01:27:49 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a file of data from which to copy.
#
set f [open data1.txt w]
................................................................................
  execsql {DELETE FROM test1}
  execsql {COPY test1 FROM 'data4.txt' USING DELIMITERS '|'}
  execsql {SELECT * FROM test1 ORDER BY one}
} {{11 } { 22 } { 33} {22 } { 33 } { 11}}

# Try copying into a table that has one or more indices.
#
do_test copy-1.8 {
  execsql {DELETE FROM test1}
  execsql {CREATE INDEX index1 ON test1(one)}
  execsql {CREATE INDEX index2 ON test1(two)}
  execsql {CREATE INDEX index3 ON test1(three)}

  execsql {COPY test1 from 'data1.txt'}
  execsql {SELECT * FROM test1 WHERE one=11}
} {11 22 33}
do_test copy-1.8b {
  execsql {SELECT * FROM test1 WHERE one=22}
} {22 33 11}
do_test copy-1.8c {
................................................................................
  execsql {CREATE TABLE test2(a int, x text)}
  set f [open data21.txt w]
  puts $f "123\t$x"
  close $f
  execsql {COPY test2 FROM 'data21.txt'}
  execsql {SELECT x from test2}
} $x

# Test the escape character mechanism
#
do_test copy-3.1 {
  set fd [open data6.txt w]
  puts $fd "hello\\\tworld\t1"
  puts $fd "hello\tworld\\\t2"
  close $fd
  execsql {
    CREATE TABLE t1(a text, b text);
    COPY t1 FROM 'data6.txt';
    SELECT * FROM t1 ORDER BY a;
  }
} {hello {world	2} {hello	world} 1}

# Cleanup 
#
file delete -force data1.txt data2.txt data3.txt data4.txt data5.txt data21.txt

finish_test