blob: e3bf5e96458821109ba3b54d3d108fd8eebb2150 [file] [log] [blame]
drh75897232000-05-29 14:26:00 +00001/*
2** Copyright (c) 1999, 2000 D. Richard Hipp
3**
4** This program is free software; you can redistribute it and/or
5** modify it under the terms of the GNU General Public
6** License as published by the Free Software Foundation; either
7** version 2 of the License, or (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12** General Public License for more details.
13**
14** You should have received a copy of the GNU General Public
15** License along with this library; if not, write to the
16** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17** Boston, MA 02111-1307, USA.
18**
19** Author contact information:
20** drh@hwaci.com
21** http://www.hwaci.com/drh/
22**
23*************************************************************************
24** This file contains code to implement the "sqlite" command line
25** utility for accessing SQLite databases.
26**
drhc08a4f12000-06-15 16:49:48 +000027** $Id: shell.c,v 1.14 2000/06/15 16:49:49 drh Exp $
drh75897232000-05-29 14:26:00 +000028*/
29#include <stdlib.h>
30#include <string.h>
31#include <stdio.h>
32#include "sqlite.h"
33#include <unistd.h>
34#include <ctype.h>
35
36#if !defined(NO_READLINE)
drh8e7e7a22000-05-30 18:45:23 +000037# include <readline/readline.h>
38# include <readline/history.h>
39#else
40# define readline getline
41# define add_history(X)
drh75897232000-05-29 14:26:00 +000042#endif
43
44/*
drh8e7e7a22000-05-30 18:45:23 +000045** This routine reads a line of text from standard input, stores
46** the text in memory obtained from malloc() and returns a pointer
47** to the text. NULL is returned at end of file, or if malloc()
48** fails.
49**
50** The interface is like "readline" but no command-line editing
51** is done.
52*/
53static char *getline(char *zPrompt){
54 char *zLine;
55 int nLine;
drh8e7e7a22000-05-30 18:45:23 +000056 int n;
57 int eol;
58
59 if( zPrompt && *zPrompt ){
60 printf("%s",zPrompt);
61 fflush(stdout);
62 }
63 nLine = 100;
64 zLine = malloc( nLine );
65 if( zLine==0 ) return 0;
66 n = 0;
67 eol = 0;
68 while( !eol ){
69 if( n+100>nLine ){
70 nLine = nLine*2 + 100;
71 zLine = realloc(zLine, nLine);
72 if( zLine==0 ) return 0;
73 }
74 if( fgets(&zLine[n], nLine - n, stdin)==0 ){
75 if( n==0 ){
76 free(zLine);
77 return 0;
78 }
79 zLine[n] = 0;
80 eol = 1;
81 break;
82 }
83 while( zLine[n] ){ n++; }
84 if( n>0 && zLine[n-1]=='\n' ){
85 n--;
86 zLine[n] = 0;
87 eol = 1;
88 }
89 }
90 zLine = realloc( zLine, n+1 );
91 return zLine;
92}
93
94/*
95** Retrieve a single line of input text. "isatty" is true if text
96** is coming from a terminal. In that case, we issue a prompt and
97** attempt to use "readline" for command-line editing. If "isatty"
98** is false, use "getline" instead of "readline" and issue to prompt.
99**
100** zPrior is a string of prior text retrieved. If not the empty
101** string, then issue a continuation prompt.
102*/
103static char *one_input_line(const char *zPrior, int isatty){
104 char *zPrompt;
105 char *zResult;
106 if( !isatty ){
107 return getline(0);
108 }
109 if( zPrior && zPrior[0] ){
110 zPrompt = " ...> ";
111 }else{
112 zPrompt = "sqlite> ";
113 }
114 zResult = readline(zPrompt);
115 add_history(zResult);
116 return zResult;
117}
118
119/*
drh75897232000-05-29 14:26:00 +0000120** An pointer to an instance of this structure is passed from
121** the main program to the callback. This is used to communicate
122** state and mode information.
123*/
124struct callback_data {
drh28bd4bc2000-06-15 15:57:22 +0000125 sqlite *db; /* The database */
126 int cnt; /* Number of records displayed so far */
127 FILE *out; /* Write results here */
128 int mode; /* An output mode setting */
129 int showHeader; /* True to show column names in List or Column mode */
130 int escape; /* Escape this character when in MODE_List */
131 char zDestTable[250]; /* Name of destination table when MODE_Insert */
132 char separator[20]; /* Separator character for MODE_List */
133 int colWidth[30]; /* Width of each column when in column mode */
drh75897232000-05-29 14:26:00 +0000134};
135
136/*
137** These are the allowed modes.
138*/
139#define MODE_Line 0 /* One field per line. Blank line between records */
140#define MODE_Column 1 /* One record per line in neat columns */
141#define MODE_List 2 /* One record per line with a separator */
drh1e5d0e92000-05-31 23:33:17 +0000142#define MODE_Html 3 /* Generate an XHTML table */
drh28bd4bc2000-06-15 15:57:22 +0000143#define MODE_Insert 4 /* Generate SQL "insert" statements */
drh75897232000-05-29 14:26:00 +0000144
145/*
146** Number of elements in an array
147*/
148#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
149
150/*
drh28bd4bc2000-06-15 15:57:22 +0000151** Return TRUE if the string supplied is a number of some kinds.
152*/
153static int is_numeric(const char *z){
154 int seen_digit = 0;
155 if( *z=='-' || *z=='+' ){
156 z++;
157 }
158 while( isdigit(*z) ){
159 seen_digit = 1;
160 z++;
161 }
162 if( seen_digit && *z=='.' ){
163 z++;
164 while( isdigit(*z) ){ z++; }
165 }
166 if( seen_digit && (*z=='e' || *z=='E')
167 && (isdigit(z[1]) || ((z[1]=='-' || z[1]=='+') && isdigit(z[2])))
168 ){
169 z+=2;
170 while( isdigit(*z) ){ z++; }
171 }
172 return seen_digit && *z==0;
173}
174
175/*
176** Output the given string as a quoted string using SQL quoting conventions.
177*/
178static void output_quoted_string(FILE *out, const char *z){
179 int i;
180 int nSingle = 0;
181 int nDouble = 0;
182 for(i=0; z[i]; i++){
183 if( z[i]=='\'' ) nSingle++;
184 else if( z[i]=='"' ) nDouble++;
185 }
186 if( nSingle==0 ){
187 fprintf(out,"'%s'",z);
188 }else if( nDouble==0 ){
189 fprintf(out,"\"%s\"",z);
190 }else{
191 fprintf(out,"'");
192 while( *z ){
193 for(i=0; z[i] && z[i]!='\''; i++){}
194 if( i==0 ){
195 fprintf(out,"''");
196 z++;
197 }else if( z[i]=='\'' ){
198 fprintf(out,"%.*s''",i,z);
199 z += i+1;
200 }else{
201 fprintf(out,"%s'",z);
202 break;
203 }
204 }
205 }
206}
207
208/*
drhc08a4f12000-06-15 16:49:48 +0000209** Output the given string with characters that are special to
210** HTML escaped.
211*/
212static void output_html_string(FILE *out, const char *z){
213 int i;
214 while( *z ){
215 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
216 if( i>0 ){
217 fprintf(out,"%.*s",i,z);
218 }
219 if( z[i]=='<' ){
220 fprintf(out,"&lt;");
221 }else if( z[i]=='&' ){
222 fprintf(out,"&amp;");
223 }else{
224 break;
225 }
226 z += i + 1;
227 }
228}
229
230/*
drh75897232000-05-29 14:26:00 +0000231** This is the callback routine that the SQLite library
232** invokes for each row of a query result.
233*/
234static int callback(void *pArg, int nArg, char **azArg, char **azCol){
235 int i;
236 struct callback_data *p = (struct callback_data*)pArg;
237 switch( p->mode ){
238 case MODE_Line: {
239 if( p->cnt++>0 ) fprintf(p->out,"\n");
240 for(i=0; i<nArg; i++){
drhc61053b2000-06-04 12:58:36 +0000241 fprintf(p->out,"%s = %s\n", azCol[i], azArg[i] ? azArg[i] : 0);
drh75897232000-05-29 14:26:00 +0000242 }
243 break;
244 }
245 case MODE_Column: {
246 if( p->cnt++==0 && p->showHeader ){
247 for(i=0; i<nArg; i++){
248 int w;
249 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
250 w = p->colWidth[i];
251 }else{
252 w = 10;
253 }
254 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
255 }
256 for(i=0; i<nArg; i++){
257 int w;
258 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
259 w = p->colWidth[i];
260 }else{
261 w = 10;
262 }
drh1e5d0e92000-05-31 23:33:17 +0000263 fprintf(p->out,"%-*.*s%s",w,w,"-------------------------------------"
264 "------------------------------------------------------------",
drh75897232000-05-29 14:26:00 +0000265 i==nArg-1 ? "\n": " ");
266 }
267 }
268 for(i=0; i<nArg; i++){
269 int w;
270 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
271 w = p->colWidth[i];
272 }else{
273 w = 10;
274 }
drhc61053b2000-06-04 12:58:36 +0000275 fprintf(p->out,"%-*.*s%s",w,w,
276 azArg[i] ? azArg[i] : "", i==nArg-1 ? "\n": " ");
drh75897232000-05-29 14:26:00 +0000277 }
278 break;
279 }
280 case MODE_List: {
281 if( p->cnt++==0 && p->showHeader ){
282 for(i=0; i<nArg; i++){
283 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
284 }
285 }
286 for(i=0; i<nArg; i++){
drh4c653a02000-06-07 01:27:47 +0000287 char *z = azArg[i];
288 if( z==0 ) z = "";
289 while( *z ){
290 int j;
291 for(j=0; z[j] && z[j]!=p->escape && z[j]!='\\'; j++){}
292 if( j>0 ){
293 fprintf(p->out, "%.*s", j, z);
294 }
295 if( z[j] ){
296 fprintf(p->out, "\\%c", z[j]);
drh670f74f2000-06-07 02:04:22 +0000297 z++;
drh4c653a02000-06-07 01:27:47 +0000298 }
drh73755922000-06-07 01:33:42 +0000299 z += j;
drh4c653a02000-06-07 01:27:47 +0000300 }
301 fprintf(p->out, "%s", i==nArg-1 ? "\n" : p->separator);
drh75897232000-05-29 14:26:00 +0000302 }
303 break;
304 }
drh1e5d0e92000-05-31 23:33:17 +0000305 case MODE_Html: {
306 if( p->cnt++==0 && p->showHeader ){
307 fprintf(p->out,"<TR>");
308 for(i=0; i<nArg; i++){
309 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
310 }
311 fprintf(p->out,"</TR>\n");
312 }
drh28bd4bc2000-06-15 15:57:22 +0000313 fprintf(p->out,"<TR>");
drh1e5d0e92000-05-31 23:33:17 +0000314 for(i=0; i<nArg; i++){
drhc08a4f12000-06-15 16:49:48 +0000315 fprintf(p->out,"<TD>");
316 output_html_string(p->out, azArg[i] ? azArg[i] : "");
317 fprintf(p->out,"</TD>\n");
drh1e5d0e92000-05-31 23:33:17 +0000318 }
drh28bd4bc2000-06-15 15:57:22 +0000319 fprintf(p->out,"</TD></TR>\n");
drh1e5d0e92000-05-31 23:33:17 +0000320 break;
321 }
drh28bd4bc2000-06-15 15:57:22 +0000322 case MODE_Insert: {
323 fprintf(p->out,"INSERT INTO '%s' VALUES(",p->zDestTable);
324 for(i=0; i<nArg; i++){
325 char *zSep = i>0 ? ",": "";
326 if( azArg[i]==0 ){
327 fprintf(p->out,"%sNULL",zSep);
328 }else if( is_numeric(azArg[i]) ){
329 fprintf(p->out,"%s%s",zSep, azArg[i]);
330 }else{
331 if( zSep[0] ) fprintf(p->out,"%s",zSep);
332 output_quoted_string(p->out, azArg[i]);
333 }
334 }
335 fprintf(p->out,");\n");
336 }
drh75897232000-05-29 14:26:00 +0000337 }
338 return 0;
339}
340
341/*
drh4c653a02000-06-07 01:27:47 +0000342** This is a different callback routine used for dumping the database.
343** Each row received by this callback consists of a table name,
344** the table type ("index" or "table") and SQL to create the table.
345** This routine should print text sufficient to recreate the table.
346*/
347static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
348 struct callback_data *pData = (struct callback_data *)pArg;
349 if( nArg!=3 ) return 1;
350 fprintf(pData->out, "%s;\n", azArg[2]);
351 if( strcmp(azArg[1],"table")==0 ){
352 struct callback_data d2;
353 char zSql[1000];
354 d2 = *pData;
355 d2.mode = MODE_List;
drh670f74f2000-06-07 02:04:22 +0000356 d2.escape = '\t';
drh4c653a02000-06-07 01:27:47 +0000357 strcpy(d2.separator,"\t");
358 fprintf(pData->out, "COPY '%s' FROM STDIN;\n", azArg[0]);
359 sprintf(zSql, "SELECT * FROM '%s'", azArg[0]);
360 sqlite_exec(pData->db, zSql, callback, &d2, 0);
361 fprintf(pData->out, "\\.\n");
362 }
drh73755922000-06-07 01:33:42 +0000363 fprintf(pData->out, "VACUUM '%s';\n", azArg[0]);
drh4c653a02000-06-07 01:27:47 +0000364 return 0;
365}
366
367/*
drh75897232000-05-29 14:26:00 +0000368** Text of a help message
369*/
370static char zHelp[] =
drh4c653a02000-06-07 01:27:47 +0000371 ".dump ?TABLE? ... Dump the database in an text format\n"
drh75897232000-05-29 14:26:00 +0000372 ".exit Exit this program\n"
373 ".explain Set output mode suitable for EXPLAIN\n"
374 ".header ON|OFF Turn display of headers on or off\n"
375 ".help Show this message\n"
376 ".indices TABLE Show names of all indices on TABLE\n"
drh1e5d0e92000-05-31 23:33:17 +0000377 ".mode MODE Set mode to one of \"line\", \"column\", "
378 "\"list\", or \"html\"\n"
drhc08a4f12000-06-15 16:49:48 +0000379 ".mode insert TABLE Generate SQL insert statements for TABLE\n"
drh75897232000-05-29 14:26:00 +0000380 ".output FILENAME Send output to FILENAME\n"
381 ".output stdout Send output to the screen\n"
382 ".schema ?TABLE? Show the CREATE statements\n"
383 ".separator STRING Change separator string for \"list\" mode\n"
384 ".tables List names all tables in the database\n"
385 ".width NUM NUM ... Set column widths for \"column\" mode\n"
386;
387
388/*
389** If an input line begins with "." then invoke this routine to
390** process that line.
391*/
392static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
393 int i = 1;
394 int nArg = 0;
395 int n, c;
396 char *azArg[50];
397
398 /* Parse the input line into tokens.
399 */
400 while( zLine[i] && nArg<ArraySize(azArg) ){
401 while( isspace(zLine[i]) ){ i++; }
402 if( zLine[i]=='\'' || zLine[i]=='"' ){
403 int delim = zLine[i++];
404 azArg[nArg++] = &zLine[i];
405 while( zLine[i] && zLine[i]!=delim ){ i++; }
406 if( zLine[i]==delim ){
407 zLine[i++] = 0;
408 }
409 }else{
410 azArg[nArg++] = &zLine[i];
411 while( zLine[i] && !isspace(zLine[i]) ){ i++; }
412 if( zLine[i] ) zLine[i++] = 0;
413 }
414 }
415
416 /* Process the input line.
417 */
418 if( nArg==0 ) return;
419 n = strlen(azArg[0]);
420 c = azArg[0][0];
drh4c653a02000-06-07 01:27:47 +0000421
422 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
423 char *zErrMsg = 0;
424 char zSql[1000];
425 if( nArg==1 ){
426 sprintf(zSql, "SELECT name, type, sql FROM sqlite_master "
427 "ORDER BY tbl_name, type DESC, name");
428 sqlite_exec(db, zSql, dump_callback, p, &zErrMsg);
429 }else{
430 int i;
431 for(i=1; i<nArg && zErrMsg==0; i++){
432 sprintf(zSql, "SELECT name, type, sql FROM sqlite_master "
433 "WHERE tbl_name LIKE '%.800s'"
434 "ORDER BY type DESC, name", azArg[i]);
435 sqlite_exec(db, zSql, dump_callback, p, &zErrMsg);
436
437 }
438 }
439 if( zErrMsg ){
440 fprintf(stderr,"Error: %s\n", zErrMsg);
441 free(zErrMsg);
442 }
443 }else
drh75897232000-05-29 14:26:00 +0000444
445 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
446 exit(0);
447 }else
448
449 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
450 p->mode = MODE_Column;
451 p->showHeader = 1;
452 p->colWidth[0] = 4;
453 p->colWidth[1] = 12;
454 p->colWidth[2] = 5;
455 p->colWidth[3] = 5;
456 p->colWidth[4] = 40;
457 }else
458
459 if( c=='h' && strncmp(azArg[0], "header", n)==0 && nArg>1 ){
460 int j;
461 char *z = azArg[1];
462 int val = atoi(azArg[1]);
463 for(j=0; z[j]; j++){
464 if( isupper(z[j]) ) z[j] = tolower(z[j]);
465 }
466 if( strcmp(z,"on")==0 ){
467 val = 1;
468 }else if( strcmp(z,"yes")==0 ){
469 val = 1;
470 }
471 p->showHeader = val;
472 }else
473
474 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
475 fprintf(stderr,zHelp);
476 }else
477
478 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
479 struct callback_data data;
480 char *zErrMsg = 0;
481 char zSql[1000];
482 memcpy(&data, p, sizeof(data));
483 data.showHeader = 0;
484 data.mode = MODE_List;
485 sprintf(zSql, "SELECT name FROM sqlite_master "
drh4c653a02000-06-07 01:27:47 +0000486 "WHERE type='index' AND tbl_name LIKE '%.800s' "
drh305cea62000-05-29 17:44:25 +0000487 "ORDER BY name", azArg[1]);
drh75897232000-05-29 14:26:00 +0000488 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
489 if( zErrMsg ){
490 fprintf(stderr,"Error: %s\n", zErrMsg);
491 free(zErrMsg);
492 }
493 }else
494
drh28bd4bc2000-06-15 15:57:22 +0000495 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
drh75897232000-05-29 14:26:00 +0000496 int n2 = strlen(azArg[1]);
497 if( strncmp(azArg[1],"line",n2)==0 ){
498 p->mode = MODE_Line;
499 }else if( strncmp(azArg[1],"column",n2)==0 ){
500 p->mode = MODE_Column;
501 }else if( strncmp(azArg[1],"list",n2)==0 ){
502 p->mode = MODE_List;
drh1e5d0e92000-05-31 23:33:17 +0000503 }else if( strncmp(azArg[1],"html",n2)==0 ){
504 p->mode = MODE_Html;
drh28bd4bc2000-06-15 15:57:22 +0000505 }else if( strncmp(azArg[1],"insert",n2)==0 ){
506 p->mode = MODE_Insert;
507 if( nArg>=3 ){
508 sprintf(p->zDestTable,"%.*s", (int)(sizeof(p->zDestTable)-1), azArg[2]);
509 }else{
510 sprintf(p->zDestTable,"table");
511 }
drh75897232000-05-29 14:26:00 +0000512 }
513 }else
514
515 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
516 if( p->out!=stdout ){
517 fclose(p->out);
518 }
519 if( strcmp(azArg[1],"stdout")==0 ){
520 p->out = stdout;
521 }else{
522 p->out = fopen(azArg[1], "w");
523 if( p->out==0 ){
524 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
525 p->out = stdout;
526 }
527 }
528 }else
529
530 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
531 struct callback_data data;
532 char *zErrMsg = 0;
533 char zSql[1000];
534 memcpy(&data, p, sizeof(data));
535 data.showHeader = 0;
536 data.mode = MODE_List;
537 if( nArg>1 ){
drh59692542000-06-07 00:12:24 +0000538 sprintf(zSql, "SELECT sql FROM sqlite_master "
539 "WHERE tbl_name LIKE '%.800s'"
540 "ORDER BY type DESC, name",
drh75897232000-05-29 14:26:00 +0000541 azArg[1]);
542 }else{
543 sprintf(zSql, "SELECT sql FROM sqlite_master "
544 "ORDER BY tbl_name, type DESC, name");
545 }
546 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
547 if( zErrMsg ){
548 fprintf(stderr,"Error: %s\n", zErrMsg);
549 free(zErrMsg);
550 }
551 }else
552
553 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
554 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
555 }else
556
557 if( c=='t' && strncmp(azArg[0], "tables", n)==0 ){
558 struct callback_data data;
559 char *zErrMsg = 0;
drh305cea62000-05-29 17:44:25 +0000560 static char zSql[] =
561 "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
drh75897232000-05-29 14:26:00 +0000562 memcpy(&data, p, sizeof(data));
563 data.showHeader = 0;
564 data.mode = MODE_List;
565 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
566 if( zErrMsg ){
567 fprintf(stderr,"Error: %s\n", zErrMsg);
568 free(zErrMsg);
569 }
570 }else
571
572 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
573 int j;
574 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
575 p->colWidth[j-1] = atoi(azArg[j]);
576 }
577 }else
578
579 {
580 fprintf(stderr, "unknown command: \"%s\". Enter \".help\" for help\n",
581 azArg[0]);
582 }
583}
584
585int main(int argc, char **argv){
586 sqlite *db;
587 char *zErrMsg = 0;
drh1e5d0e92000-05-31 23:33:17 +0000588 char *argv0 = argv[0];
drh75897232000-05-29 14:26:00 +0000589 struct callback_data data;
590
drh1e5d0e92000-05-31 23:33:17 +0000591 memset(&data, 0, sizeof(data));
592 data.mode = MODE_List;
593 strcpy(data.separator,"|");
594 data.showHeader = 0;
595 while( argc>=2 && argv[1][0]=='-' ){
596 if( strcmp(argv[1],"-html")==0 ){
597 data.mode = MODE_Html;
598 argc--;
599 argv++;
600 }else if( strcmp(argv[1],"-list")==0 ){
601 data.mode = MODE_List;
602 argc--;
603 argv++;
604 }else if( strcmp(argv[1],"-line")==0 ){
605 data.mode = MODE_Line;
606 argc--;
607 argv++;
608 }else if( argc>=3 && strcmp(argv[0],"-separator")==0 ){
drhbed86902000-06-02 13:27:59 +0000609 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[2]);
drh1e5d0e92000-05-31 23:33:17 +0000610 argc -= 2;
611 argv += 2;
612 }else if( strcmp(argv[1],"-header")==0 ){
613 data.showHeader = 1;
614 argc--;
615 argv++;
616 }else if( strcmp(argv[1],"-noheader")==0 ){
617 data.showHeader = 0;
618 argc--;
619 argv++;
620 }else{
621 fprintf(stderr,"%s: unknown option: %s\n", argv0, argv[1]);
622 return 1;
623 }
624 }
drh75897232000-05-29 14:26:00 +0000625 if( argc!=2 && argc!=3 ){
drh1e5d0e92000-05-31 23:33:17 +0000626 fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
drh75897232000-05-29 14:26:00 +0000627 exit(1);
628 }
drh4c653a02000-06-07 01:27:47 +0000629 data.db = db = sqlite_open(argv[1], 0666, &zErrMsg);
drh75897232000-05-29 14:26:00 +0000630 if( db==0 ){
drhd1dedb82000-06-05 02:07:04 +0000631 if( zErrMsg ){
632 fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1], zErrMsg);
633 }else{
634 fprintf(stderr,"Unable to open database %s\n", argv[1]);
635 }
drh75897232000-05-29 14:26:00 +0000636 exit(1);
637 }
drh75897232000-05-29 14:26:00 +0000638 data.out = stdout;
639 if( argc==3 ){
drh75897232000-05-29 14:26:00 +0000640 if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
641 fprintf(stderr,"SQL error: %s\n", zErrMsg);
642 exit(1);
643 }
644 }else{
645 char *zLine;
646 char *zSql = 0;
647 int nSql = 0;
648 int istty = isatty(0);
drh75897232000-05-29 14:26:00 +0000649 if( istty ){
650 printf(
651 "Enter \".help\" for instructions\n"
652 );
653 }
drh8e7e7a22000-05-30 18:45:23 +0000654 while( (zLine = one_input_line(zSql, istty))!=0 ){
drh75897232000-05-29 14:26:00 +0000655 if( zLine && zLine[0]=='.' ){
656 do_meta_command(zLine, db, &data);
657 free(zLine);
658 continue;
659 }
660 if( zSql==0 ){
661 nSql = strlen(zLine);
662 zSql = malloc( nSql+1 );
663 strcpy(zSql, zLine);
664 }else{
665 int len = strlen(zLine);
666 zSql = realloc( zSql, nSql + len + 2 );
667 if( zSql==0 ){
drh1e5d0e92000-05-31 23:33:17 +0000668 fprintf(stderr,"%s: out of memory!\n", argv0);
drh75897232000-05-29 14:26:00 +0000669 exit(1);
670 }
671 strcpy(&zSql[nSql++], "\n");
672 strcpy(&zSql[nSql], zLine);
673 nSql += len;
674 }
675 free(zLine);
676 if( sqlite_complete(zSql) ){
677 data.cnt = 0;
678 if( sqlite_exec(db, zSql, callback, &data, &zErrMsg)!=0
679 && zErrMsg!=0 ){
680 printf("SQL error: %s\n", zErrMsg);
681 free(zErrMsg);
682 zErrMsg = 0;
683 }
684 free(zSql);
685 zSql = 0;
686 nSql = 0;
687 }
688 }
689 }
690 sqlite_close(db);
691 return 0;
692}