|
1 /* |
|
2 ** 2001 September 15 |
|
3 ** |
|
4 ** The author disclaims copyright to this source code. In place of |
|
5 ** a legal notice, here is a blessing: |
|
6 ** |
|
7 ** May you do good and not evil. |
|
8 ** May you find forgiveness for yourself and forgive others. |
|
9 ** May you share freely, never taking more than you give. |
|
10 ** |
|
11 ************************************************************************* |
|
12 ** This file contains code to implement the "sqlite" command line |
|
13 ** utility for accessing SQLite databases. |
|
14 ** |
|
15 ** $Id: shell.c,v 1.147 2006/08/29 12:04:19 drh Exp $ |
|
16 */ |
|
17 #include <stdlib.h> |
|
18 #include <string.h> |
|
19 #include <stdio.h> |
|
20 #include <assert.h> |
|
21 #include "sqlite3.h" |
|
22 #include <ctype.h> |
|
23 |
|
24 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__) |
|
25 # include <signal.h> |
|
26 # include <pwd.h> |
|
27 # include <unistd.h> |
|
28 # include <sys/types.h> |
|
29 #endif |
|
30 |
|
31 #ifdef __MACOS__ |
|
32 # include <console.h> |
|
33 # include <signal.h> |
|
34 # include <unistd.h> |
|
35 # include <extras.h> |
|
36 # include <Files.h> |
|
37 # include <Folders.h> |
|
38 #endif |
|
39 |
|
40 #ifdef __OS2__ |
|
41 # include <unistd.h> |
|
42 #endif |
|
43 |
|
44 #if defined(HAVE_READLINE) && HAVE_READLINE==1 |
|
45 # include <readline/readline.h> |
|
46 # include <readline/history.h> |
|
47 #else |
|
48 # define readline(p) local_getline(p,stdin) |
|
49 # define add_history(X) |
|
50 # define read_history(X) |
|
51 # define write_history(X) |
|
52 # define stifle_history(X) |
|
53 #endif |
|
54 |
|
55 /* Make sure isatty() has a prototype. |
|
56 */ |
|
57 extern int isatty(); |
|
58 |
|
59 /* |
|
60 ** The following is the open SQLite database. We make a pointer |
|
61 ** to this database a static variable so that it can be accessed |
|
62 ** by the SIGINT handler to interrupt database processing. |
|
63 */ |
|
64 static sqlite3 *db = 0; |
|
65 |
|
66 /* |
|
67 ** True if an interrupt (Control-C) has been received. |
|
68 */ |
|
69 static volatile int seenInterrupt = 0; |
|
70 |
|
71 /* |
|
72 ** This is the name of our program. It is set in main(), used |
|
73 ** in a number of other places, mostly for error messages. |
|
74 */ |
|
75 static char *Argv0; |
|
76 |
|
77 /* |
|
78 ** Prompt strings. Initialized in main. Settable with |
|
79 ** .prompt main continue |
|
80 */ |
|
81 static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ |
|
82 static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ |
|
83 |
|
84 |
|
85 /* |
|
86 ** Determines if a string is a number of not. |
|
87 */ |
|
88 static int isNumber(const char *z, int *realnum){ |
|
89 if( *z=='-' || *z=='+' ) z++; |
|
90 if( !isdigit(*z) ){ |
|
91 return 0; |
|
92 } |
|
93 z++; |
|
94 if( realnum ) *realnum = 0; |
|
95 while( isdigit(*z) ){ z++; } |
|
96 if( *z=='.' ){ |
|
97 z++; |
|
98 if( !isdigit(*z) ) return 0; |
|
99 while( isdigit(*z) ){ z++; } |
|
100 if( realnum ) *realnum = 1; |
|
101 } |
|
102 if( *z=='e' || *z=='E' ){ |
|
103 z++; |
|
104 if( *z=='+' || *z=='-' ) z++; |
|
105 if( !isdigit(*z) ) return 0; |
|
106 while( isdigit(*z) ){ z++; } |
|
107 if( realnum ) *realnum = 1; |
|
108 } |
|
109 return *z==0; |
|
110 } |
|
111 |
|
112 /* |
|
113 ** A global char* and an SQL function to access its current value |
|
114 ** from within an SQL statement. This program used to use the |
|
115 ** sqlite_exec_printf() API to substitue a string into an SQL statement. |
|
116 ** The correct way to do this with sqlite3 is to use the bind API, but |
|
117 ** since the shell is built around the callback paradigm it would be a lot |
|
118 ** of work. Instead just use this hack, which is quite harmless. |
|
119 */ |
|
120 static const char *zShellStatic = 0; |
|
121 static void shellstaticFunc( |
|
122 sqlite3_context *context, |
|
123 int argc, |
|
124 sqlite3_value **argv |
|
125 ){ |
|
126 assert( 0==argc ); |
|
127 assert( zShellStatic ); |
|
128 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); |
|
129 } |
|
130 |
|
131 |
|
132 /* |
|
133 ** This routine reads a line of text from FILE in, stores |
|
134 ** the text in memory obtained from malloc() and returns a pointer |
|
135 ** to the text. NULL is returned at end of file, or if malloc() |
|
136 ** fails. |
|
137 ** |
|
138 ** The interface is like "readline" but no command-line editing |
|
139 ** is done. |
|
140 */ |
|
141 static char *local_getline(char *zPrompt, FILE *in){ |
|
142 char *zLine; |
|
143 int nLine; |
|
144 int n; |
|
145 int eol; |
|
146 |
|
147 if( zPrompt && *zPrompt ){ |
|
148 printf("%s",zPrompt); |
|
149 fflush(stdout); |
|
150 } |
|
151 nLine = 100; |
|
152 zLine = malloc( nLine ); |
|
153 if( zLine==0 ) return 0; |
|
154 n = 0; |
|
155 eol = 0; |
|
156 while( !eol ){ |
|
157 if( n+100>nLine ){ |
|
158 nLine = nLine*2 + 100; |
|
159 zLine = realloc(zLine, nLine); |
|
160 if( zLine==0 ) return 0; |
|
161 } |
|
162 if( fgets(&zLine[n], nLine - n, in)==0 ){ |
|
163 if( n==0 ){ |
|
164 free(zLine); |
|
165 return 0; |
|
166 } |
|
167 zLine[n] = 0; |
|
168 eol = 1; |
|
169 break; |
|
170 } |
|
171 while( zLine[n] ){ n++; } |
|
172 if( n>0 && zLine[n-1]=='\n' ){ |
|
173 n--; |
|
174 zLine[n] = 0; |
|
175 eol = 1; |
|
176 } |
|
177 } |
|
178 zLine = realloc( zLine, n+1 ); |
|
179 return zLine; |
|
180 } |
|
181 |
|
182 /* |
|
183 ** Retrieve a single line of input text. "isatty" is true if text |
|
184 ** is coming from a terminal. In that case, we issue a prompt and |
|
185 ** attempt to use "readline" for command-line editing. If "isatty" |
|
186 ** is false, use "local_getline" instead of "readline" and issue no prompt. |
|
187 ** |
|
188 ** zPrior is a string of prior text retrieved. If not the empty |
|
189 ** string, then issue a continuation prompt. |
|
190 */ |
|
191 static char *one_input_line(const char *zPrior, FILE *in){ |
|
192 char *zPrompt; |
|
193 char *zResult; |
|
194 if( in!=0 ){ |
|
195 return local_getline(0, in); |
|
196 } |
|
197 if( zPrior && zPrior[0] ){ |
|
198 zPrompt = continuePrompt; |
|
199 }else{ |
|
200 zPrompt = mainPrompt; |
|
201 } |
|
202 zResult = readline(zPrompt); |
|
203 #if defined(HAVE_READLINE) && HAVE_READLINE==1 |
|
204 if( zResult && *zResult ) add_history(zResult); |
|
205 #endif |
|
206 return zResult; |
|
207 } |
|
208 |
|
209 struct previous_mode_data { |
|
210 int valid; /* Is there legit data in here? */ |
|
211 int mode; |
|
212 int showHeader; |
|
213 int colWidth[100]; |
|
214 }; |
|
215 /* |
|
216 ** An pointer to an instance of this structure is passed from |
|
217 ** the main program to the callback. This is used to communicate |
|
218 ** state and mode information. |
|
219 */ |
|
220 struct callback_data { |
|
221 sqlite3 *db; /* The database */ |
|
222 int echoOn; /* True to echo input commands */ |
|
223 int cnt; /* Number of records displayed so far */ |
|
224 FILE *out; /* Write results here */ |
|
225 int mode; /* An output mode setting */ |
|
226 int showHeader; /* True to show column names in List or Column mode */ |
|
227 char *zDestTable; /* Name of destination table when MODE_Insert */ |
|
228 char separator[20]; /* Separator character for MODE_List */ |
|
229 int colWidth[100]; /* Requested width of each column when in column mode*/ |
|
230 int actualWidth[100]; /* Actual width of each column */ |
|
231 char nullvalue[20]; /* The text to print when a NULL comes back from |
|
232 ** the database */ |
|
233 struct previous_mode_data explainPrev; |
|
234 /* Holds the mode information just before |
|
235 ** .explain ON */ |
|
236 char outfile[FILENAME_MAX]; /* Filename for *out */ |
|
237 const char *zDbFilename; /* name of the database file */ |
|
238 char *zKey; /* Encryption key */ |
|
239 }; |
|
240 |
|
241 /* |
|
242 ** These are the allowed modes. |
|
243 */ |
|
244 #define MODE_Line 0 /* One column per line. Blank line between records */ |
|
245 #define MODE_Column 1 /* One record per line in neat columns */ |
|
246 #define MODE_List 2 /* One record per line with a separator */ |
|
247 #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
|
248 #define MODE_Html 4 /* Generate an XHTML table */ |
|
249 #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
|
250 #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ |
|
251 #define MODE_Csv 7 /* Quote strings, numbers are plain */ |
|
252 #define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */ |
|
253 |
|
254 static const char *modeDescr[MODE_NUM_OF] = { |
|
255 "line", |
|
256 "column", |
|
257 "list", |
|
258 "semi", |
|
259 "html", |
|
260 "insert", |
|
261 "tcl", |
|
262 "csv", |
|
263 }; |
|
264 |
|
265 /* |
|
266 ** Number of elements in an array |
|
267 */ |
|
268 #define ArraySize(X) (sizeof(X)/sizeof(X[0])) |
|
269 |
|
270 /* |
|
271 ** Output the given string as a quoted string using SQL quoting conventions. |
|
272 */ |
|
273 static void output_quoted_string(FILE *out, const char *z){ |
|
274 int i; |
|
275 int nSingle = 0; |
|
276 for(i=0; z[i]; i++){ |
|
277 if( z[i]=='\'' ) nSingle++; |
|
278 } |
|
279 if( nSingle==0 ){ |
|
280 fprintf(out,"'%s'",z); |
|
281 }else{ |
|
282 fprintf(out,"'"); |
|
283 while( *z ){ |
|
284 for(i=0; z[i] && z[i]!='\''; i++){} |
|
285 if( i==0 ){ |
|
286 fprintf(out,"''"); |
|
287 z++; |
|
288 }else if( z[i]=='\'' ){ |
|
289 fprintf(out,"%.*s''",i,z); |
|
290 z += i+1; |
|
291 }else{ |
|
292 fprintf(out,"%s",z); |
|
293 break; |
|
294 } |
|
295 } |
|
296 fprintf(out,"'"); |
|
297 } |
|
298 } |
|
299 |
|
300 /* |
|
301 ** Output the given string as a quoted according to C or TCL quoting rules. |
|
302 */ |
|
303 static void output_c_string(FILE *out, const char *z){ |
|
304 unsigned int c; |
|
305 fputc('"', out); |
|
306 while( (c = *(z++))!=0 ){ |
|
307 if( c=='\\' ){ |
|
308 fputc(c, out); |
|
309 fputc(c, out); |
|
310 }else if( c=='\t' ){ |
|
311 fputc('\\', out); |
|
312 fputc('t', out); |
|
313 }else if( c=='\n' ){ |
|
314 fputc('\\', out); |
|
315 fputc('n', out); |
|
316 }else if( c=='\r' ){ |
|
317 fputc('\\', out); |
|
318 fputc('r', out); |
|
319 }else if( !isprint(c) ){ |
|
320 fprintf(out, "\\%03o", c&0xff); |
|
321 }else{ |
|
322 fputc(c, out); |
|
323 } |
|
324 } |
|
325 fputc('"', out); |
|
326 } |
|
327 |
|
328 /* |
|
329 ** Output the given string with characters that are special to |
|
330 ** HTML escaped. |
|
331 */ |
|
332 static void output_html_string(FILE *out, const char *z){ |
|
333 int i; |
|
334 while( *z ){ |
|
335 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){} |
|
336 if( i>0 ){ |
|
337 fprintf(out,"%.*s",i,z); |
|
338 } |
|
339 if( z[i]=='<' ){ |
|
340 fprintf(out,"<"); |
|
341 }else if( z[i]=='&' ){ |
|
342 fprintf(out,"&"); |
|
343 }else{ |
|
344 break; |
|
345 } |
|
346 z += i + 1; |
|
347 } |
|
348 } |
|
349 |
|
350 /* |
|
351 ** Output a single term of CSV. Actually, p->separator is used for |
|
352 ** the separator, which may or may not be a comma. p->nullvalue is |
|
353 ** the null value. Strings are quoted using ANSI-C rules. Numbers |
|
354 ** appear outside of quotes. |
|
355 */ |
|
356 static void output_csv(struct callback_data *p, const char *z, int bSep){ |
|
357 if( z==0 ){ |
|
358 fprintf(p->out,"%s",p->nullvalue); |
|
359 }else if( isNumber(z, 0) ){ |
|
360 fprintf(p->out,"%s",z); |
|
361 }else{ |
|
362 output_c_string(p->out, z); |
|
363 } |
|
364 if( bSep ){ |
|
365 fprintf(p->out, p->separator); |
|
366 } |
|
367 } |
|
368 |
|
369 #ifdef SIGINT |
|
370 /* |
|
371 ** This routine runs when the user presses Ctrl-C |
|
372 */ |
|
373 static void interrupt_handler(int NotUsed){ |
|
374 seenInterrupt = 1; |
|
375 if( db ) sqlite3_interrupt(db); |
|
376 } |
|
377 #endif |
|
378 |
|
379 /* |
|
380 ** This is the callback routine that the SQLite library |
|
381 ** invokes for each row of a query result. |
|
382 */ |
|
383 static int callback(void *pArg, int nArg, char **azArg, char **azCol){ |
|
384 int i; |
|
385 struct callback_data *p = (struct callback_data*)pArg; |
|
386 switch( p->mode ){ |
|
387 case MODE_Line: { |
|
388 int w = 5; |
|
389 if( azArg==0 ) break; |
|
390 for(i=0; i<nArg; i++){ |
|
391 int len = strlen(azCol[i] ? azCol[i] : ""); |
|
392 if( len>w ) w = len; |
|
393 } |
|
394 if( p->cnt++>0 ) fprintf(p->out,"\n"); |
|
395 for(i=0; i<nArg; i++){ |
|
396 fprintf(p->out,"%*s = %s\n", w, azCol[i], |
|
397 azArg[i] ? azArg[i] : p->nullvalue); |
|
398 } |
|
399 break; |
|
400 } |
|
401 case MODE_Column: { |
|
402 if( p->cnt++==0 ){ |
|
403 for(i=0; i<nArg; i++){ |
|
404 int w, n; |
|
405 if( i<ArraySize(p->colWidth) ){ |
|
406 w = p->colWidth[i]; |
|
407 }else{ |
|
408 w = 0; |
|
409 } |
|
410 if( w<=0 ){ |
|
411 w = strlen(azCol[i] ? azCol[i] : ""); |
|
412 if( w<10 ) w = 10; |
|
413 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue); |
|
414 if( w<n ) w = n; |
|
415 } |
|
416 if( i<ArraySize(p->actualWidth) ){ |
|
417 p->actualWidth[i] = w; |
|
418 } |
|
419 if( p->showHeader ){ |
|
420 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); |
|
421 } |
|
422 } |
|
423 if( p->showHeader ){ |
|
424 for(i=0; i<nArg; i++){ |
|
425 int w; |
|
426 if( i<ArraySize(p->actualWidth) ){ |
|
427 w = p->actualWidth[i]; |
|
428 }else{ |
|
429 w = 10; |
|
430 } |
|
431 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" |
|
432 "----------------------------------------------------------", |
|
433 i==nArg-1 ? "\n": " "); |
|
434 } |
|
435 } |
|
436 } |
|
437 if( azArg==0 ) break; |
|
438 for(i=0; i<nArg; i++){ |
|
439 int w; |
|
440 if( i<ArraySize(p->actualWidth) ){ |
|
441 w = p->actualWidth[i]; |
|
442 }else{ |
|
443 w = 10; |
|
444 } |
|
445 fprintf(p->out,"%-*.*s%s",w,w, |
|
446 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); |
|
447 } |
|
448 break; |
|
449 } |
|
450 case MODE_Semi: |
|
451 case MODE_List: { |
|
452 if( p->cnt++==0 && p->showHeader ){ |
|
453 for(i=0; i<nArg; i++){ |
|
454 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); |
|
455 } |
|
456 } |
|
457 if( azArg==0 ) break; |
|
458 for(i=0; i<nArg; i++){ |
|
459 char *z = azArg[i]; |
|
460 if( z==0 ) z = p->nullvalue; |
|
461 fprintf(p->out, "%s", z); |
|
462 if( i<nArg-1 ){ |
|
463 fprintf(p->out, "%s", p->separator); |
|
464 }else if( p->mode==MODE_Semi ){ |
|
465 fprintf(p->out, ";\n"); |
|
466 }else{ |
|
467 fprintf(p->out, "\n"); |
|
468 } |
|
469 } |
|
470 break; |
|
471 } |
|
472 case MODE_Html: { |
|
473 if( p->cnt++==0 && p->showHeader ){ |
|
474 fprintf(p->out,"<TR>"); |
|
475 for(i=0; i<nArg; i++){ |
|
476 fprintf(p->out,"<TH>%s</TH>",azCol[i]); |
|
477 } |
|
478 fprintf(p->out,"</TR>\n"); |
|
479 } |
|
480 if( azArg==0 ) break; |
|
481 fprintf(p->out,"<TR>"); |
|
482 for(i=0; i<nArg; i++){ |
|
483 fprintf(p->out,"<TD>"); |
|
484 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); |
|
485 fprintf(p->out,"</TD>\n"); |
|
486 } |
|
487 fprintf(p->out,"</TR>\n"); |
|
488 break; |
|
489 } |
|
490 case MODE_Tcl: { |
|
491 if( p->cnt++==0 && p->showHeader ){ |
|
492 for(i=0; i<nArg; i++){ |
|
493 output_c_string(p->out,azCol[i] ? azCol[i] : ""); |
|
494 fprintf(p->out, "%s", p->separator); |
|
495 } |
|
496 fprintf(p->out,"\n"); |
|
497 } |
|
498 if( azArg==0 ) break; |
|
499 for(i=0; i<nArg; i++){ |
|
500 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); |
|
501 fprintf(p->out, "%s", p->separator); |
|
502 } |
|
503 fprintf(p->out,"\n"); |
|
504 break; |
|
505 } |
|
506 case MODE_Csv: { |
|
507 if( p->cnt++==0 && p->showHeader ){ |
|
508 for(i=0; i<nArg; i++){ |
|
509 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
|
510 } |
|
511 fprintf(p->out,"\n"); |
|
512 } |
|
513 if( azArg==0 ) break; |
|
514 for(i=0; i<nArg; i++){ |
|
515 output_csv(p, azArg[i], i<nArg-1); |
|
516 } |
|
517 fprintf(p->out,"\n"); |
|
518 break; |
|
519 } |
|
520 case MODE_Insert: { |
|
521 if( azArg==0 ) break; |
|
522 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); |
|
523 for(i=0; i<nArg; i++){ |
|
524 char *zSep = i>0 ? ",": ""; |
|
525 if( azArg[i]==0 ){ |
|
526 fprintf(p->out,"%sNULL",zSep); |
|
527 }else if( isNumber(azArg[i], 0) ){ |
|
528 fprintf(p->out,"%s%s",zSep, azArg[i]); |
|
529 }else{ |
|
530 if( zSep[0] ) fprintf(p->out,"%s",zSep); |
|
531 output_quoted_string(p->out, azArg[i]); |
|
532 } |
|
533 } |
|
534 fprintf(p->out,");\n"); |
|
535 break; |
|
536 } |
|
537 } |
|
538 return 0; |
|
539 } |
|
540 |
|
541 /* |
|
542 ** Set the destination table field of the callback_data structure to |
|
543 ** the name of the table given. Escape any quote characters in the |
|
544 ** table name. |
|
545 */ |
|
546 static void set_table_name(struct callback_data *p, const char *zName){ |
|
547 int i, n; |
|
548 int needQuote; |
|
549 char *z; |
|
550 |
|
551 if( p->zDestTable ){ |
|
552 free(p->zDestTable); |
|
553 p->zDestTable = 0; |
|
554 } |
|
555 if( zName==0 ) return; |
|
556 needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; |
|
557 for(i=n=0; zName[i]; i++, n++){ |
|
558 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ |
|
559 needQuote = 1; |
|
560 if( zName[i]=='\'' ) n++; |
|
561 } |
|
562 } |
|
563 if( needQuote ) n += 2; |
|
564 z = p->zDestTable = malloc( n+1 ); |
|
565 if( z==0 ){ |
|
566 fprintf(stderr,"Out of memory!\n"); |
|
567 exit(1); |
|
568 } |
|
569 n = 0; |
|
570 if( needQuote ) z[n++] = '\''; |
|
571 for(i=0; zName[i]; i++){ |
|
572 z[n++] = zName[i]; |
|
573 if( zName[i]=='\'' ) z[n++] = '\''; |
|
574 } |
|
575 if( needQuote ) z[n++] = '\''; |
|
576 z[n] = 0; |
|
577 } |
|
578 |
|
579 /* zIn is either a pointer to a NULL-terminated string in memory obtained |
|
580 ** from malloc(), or a NULL pointer. The string pointed to by zAppend is |
|
581 ** added to zIn, and the result returned in memory obtained from malloc(). |
|
582 ** zIn, if it was not NULL, is freed. |
|
583 ** |
|
584 ** If the third argument, quote, is not '\0', then it is used as a |
|
585 ** quote character for zAppend. |
|
586 */ |
|
587 static char * appendText(char *zIn, char const *zAppend, char quote){ |
|
588 int len; |
|
589 int i; |
|
590 int nAppend = strlen(zAppend); |
|
591 int nIn = (zIn?strlen(zIn):0); |
|
592 |
|
593 len = nAppend+nIn+1; |
|
594 if( quote ){ |
|
595 len += 2; |
|
596 for(i=0; i<nAppend; i++){ |
|
597 if( zAppend[i]==quote ) len++; |
|
598 } |
|
599 } |
|
600 |
|
601 zIn = (char *)realloc(zIn, len); |
|
602 if( !zIn ){ |
|
603 return 0; |
|
604 } |
|
605 |
|
606 if( quote ){ |
|
607 char *zCsr = &zIn[nIn]; |
|
608 *zCsr++ = quote; |
|
609 for(i=0; i<nAppend; i++){ |
|
610 *zCsr++ = zAppend[i]; |
|
611 if( zAppend[i]==quote ) *zCsr++ = quote; |
|
612 } |
|
613 *zCsr++ = quote; |
|
614 *zCsr++ = '\0'; |
|
615 assert( (zCsr-zIn)==len ); |
|
616 }else{ |
|
617 memcpy(&zIn[nIn], zAppend, nAppend); |
|
618 zIn[len-1] = '\0'; |
|
619 } |
|
620 |
|
621 return zIn; |
|
622 } |
|
623 |
|
624 |
|
625 /* |
|
626 ** Execute a query statement that has a single result column. Print |
|
627 ** that result column on a line by itself with a semicolon terminator. |
|
628 */ |
|
629 static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){ |
|
630 sqlite3_stmt *pSelect; |
|
631 int rc; |
|
632 rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0); |
|
633 if( rc!=SQLITE_OK || !pSelect ){ |
|
634 return rc; |
|
635 } |
|
636 rc = sqlite3_step(pSelect); |
|
637 while( rc==SQLITE_ROW ){ |
|
638 fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0)); |
|
639 rc = sqlite3_step(pSelect); |
|
640 } |
|
641 return sqlite3_finalize(pSelect); |
|
642 } |
|
643 |
|
644 |
|
645 /* |
|
646 ** This is a different callback routine used for dumping the database. |
|
647 ** Each row received by this callback consists of a table name, |
|
648 ** the table type ("index" or "table") and SQL to create the table. |
|
649 ** This routine should print text sufficient to recreate the table. |
|
650 */ |
|
651 static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ |
|
652 int rc; |
|
653 const char *zTable; |
|
654 const char *zType; |
|
655 const char *zSql; |
|
656 struct callback_data *p = (struct callback_data *)pArg; |
|
657 |
|
658 if( nArg!=3 ) return 1; |
|
659 zTable = azArg[0]; |
|
660 zType = azArg[1]; |
|
661 zSql = azArg[2]; |
|
662 |
|
663 if( strcmp(zTable, "sqlite_sequence")==0 ){ |
|
664 fprintf(p->out, "DELETE FROM sqlite_sequence;\n"); |
|
665 }else if( strcmp(zTable, "sqlite_stat1")==0 ){ |
|
666 fprintf(p->out, "ANALYZE sqlite_master;\n"); |
|
667 }else if( strncmp(zTable, "sqlite_", 7)==0 ){ |
|
668 return 0; |
|
669 }else{ |
|
670 fprintf(p->out, "%s;\n", zSql); |
|
671 } |
|
672 |
|
673 if( strcmp(zType, "table")==0 ){ |
|
674 sqlite3_stmt *pTableInfo = 0; |
|
675 char *zSelect = 0; |
|
676 char *zTableInfo = 0; |
|
677 char *zTmp = 0; |
|
678 |
|
679 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); |
|
680 zTableInfo = appendText(zTableInfo, zTable, '"'); |
|
681 zTableInfo = appendText(zTableInfo, ");", 0); |
|
682 |
|
683 rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); |
|
684 if( zTableInfo ) free(zTableInfo); |
|
685 if( rc!=SQLITE_OK || !pTableInfo ){ |
|
686 return 1; |
|
687 } |
|
688 |
|
689 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); |
|
690 zTmp = appendText(zTmp, zTable, '"'); |
|
691 if( zTmp ){ |
|
692 zSelect = appendText(zSelect, zTmp, '\''); |
|
693 } |
|
694 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); |
|
695 rc = sqlite3_step(pTableInfo); |
|
696 while( rc==SQLITE_ROW ){ |
|
697 const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); |
|
698 zSelect = appendText(zSelect, "quote(", 0); |
|
699 zSelect = appendText(zSelect, zText, '"'); |
|
700 rc = sqlite3_step(pTableInfo); |
|
701 if( rc==SQLITE_ROW ){ |
|
702 zSelect = appendText(zSelect, ") || ', ' || ", 0); |
|
703 }else{ |
|
704 zSelect = appendText(zSelect, ") ", 0); |
|
705 } |
|
706 } |
|
707 rc = sqlite3_finalize(pTableInfo); |
|
708 if( rc!=SQLITE_OK ){ |
|
709 if( zSelect ) free(zSelect); |
|
710 return 1; |
|
711 } |
|
712 zSelect = appendText(zSelect, "|| ')' FROM ", 0); |
|
713 zSelect = appendText(zSelect, zTable, '"'); |
|
714 |
|
715 rc = run_table_dump_query(p->out, p->db, zSelect); |
|
716 if( rc==SQLITE_CORRUPT ){ |
|
717 zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); |
|
718 rc = run_table_dump_query(p->out, p->db, zSelect); |
|
719 } |
|
720 if( zSelect ) free(zSelect); |
|
721 if( rc!=SQLITE_OK ){ |
|
722 return 1; |
|
723 } |
|
724 } |
|
725 return 0; |
|
726 } |
|
727 |
|
728 /* |
|
729 ** Run zQuery. Update dump_callback() as the callback routine. |
|
730 ** If we get a SQLITE_CORRUPT error, rerun the query after appending |
|
731 ** "ORDER BY rowid DESC" to the end. |
|
732 */ |
|
733 static int run_schema_dump_query( |
|
734 struct callback_data *p, |
|
735 const char *zQuery, |
|
736 char **pzErrMsg |
|
737 ){ |
|
738 int rc; |
|
739 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg); |
|
740 if( rc==SQLITE_CORRUPT ){ |
|
741 char *zQ2; |
|
742 int len = strlen(zQuery); |
|
743 if( pzErrMsg ) sqlite3_free(*pzErrMsg); |
|
744 zQ2 = malloc( len+100 ); |
|
745 if( zQ2==0 ) return rc; |
|
746 sprintf(zQ2, "%s ORDER BY rowid DESC", zQuery); |
|
747 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg); |
|
748 free(zQ2); |
|
749 } |
|
750 return rc; |
|
751 } |
|
752 |
|
753 /* |
|
754 ** Text of a help message |
|
755 */ |
|
756 static char zHelp[] = |
|
757 ".databases List names and files of attached databases\n" |
|
758 ".dump ?TABLE? ... Dump the database in an SQL text format\n" |
|
759 ".echo ON|OFF Turn command echo on or off\n" |
|
760 ".exit Exit this program\n" |
|
761 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n" |
|
762 ".header(s) ON|OFF Turn display of headers on or off\n" |
|
763 ".help Show this message\n" |
|
764 ".import FILE TABLE Import data from FILE into TABLE\n" |
|
765 ".indices TABLE Show names of all indices on TABLE\n" |
|
766 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
|
767 ".load FILE ?ENTRY? Load an extension library\n" |
|
768 #endif |
|
769 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" |
|
770 " csv Comma-separated values\n" |
|
771 " column Left-aligned columns. (See .width)\n" |
|
772 " html HTML <table> code\n" |
|
773 " insert SQL insert statements for TABLE\n" |
|
774 " line One value per line\n" |
|
775 " list Values delimited by .separator string\n" |
|
776 " tabs Tab-separated values\n" |
|
777 " tcl TCL list elements\n" |
|
778 ".nullvalue STRING Print STRING in place of NULL values\n" |
|
779 ".output FILENAME Send output to FILENAME\n" |
|
780 ".output stdout Send output to the screen\n" |
|
781 ".prompt MAIN CONTINUE Replace the standard prompts\n" |
|
782 ".quit Exit this program\n" |
|
783 ".read FILENAME Execute SQL in FILENAME\n" |
|
784 ".schema ?TABLE? Show the CREATE statements\n" |
|
785 ".separator STRING Change separator used by output mode and .import\n" |
|
786 ".show Show the current values for various settings\n" |
|
787 ".tables ?PATTERN? List names of tables matching a LIKE pattern\n" |
|
788 ".timeout MS Try opening locked tables for MS milliseconds\n" |
|
789 ".width NUM NUM ... Set column widths for \"column\" mode\n" |
|
790 ; |
|
791 |
|
792 /* Forward reference */ |
|
793 static void process_input(struct callback_data *p, FILE *in); |
|
794 |
|
795 /* |
|
796 ** Make sure the database is open. If it is not, then open it. If |
|
797 ** the database fails to open, print an error message and exit. |
|
798 */ |
|
799 static void open_db(struct callback_data *p){ |
|
800 if( p->db==0 ){ |
|
801 sqlite3_open(p->zDbFilename, &p->db); |
|
802 db = p->db; |
|
803 sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, |
|
804 shellstaticFunc, 0, 0); |
|
805 if( SQLITE_OK!=sqlite3_errcode(db) ){ |
|
806 fprintf(stderr,"Unable to open database \"%s\": %s\n", |
|
807 p->zDbFilename, sqlite3_errmsg(db)); |
|
808 exit(1); |
|
809 } |
|
810 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
|
811 sqlite3_enable_load_extension(p->db, 1); |
|
812 #endif |
|
813 } |
|
814 } |
|
815 |
|
816 /* |
|
817 ** Do C-language style dequoting. |
|
818 ** |
|
819 ** \t -> tab |
|
820 ** \n -> newline |
|
821 ** \r -> carriage return |
|
822 ** \NNN -> ascii character NNN in octal |
|
823 ** \\ -> backslash |
|
824 */ |
|
825 static void resolve_backslashes(char *z){ |
|
826 int i, j, c; |
|
827 for(i=j=0; (c = z[i])!=0; i++, j++){ |
|
828 if( c=='\\' ){ |
|
829 c = z[++i]; |
|
830 if( c=='n' ){ |
|
831 c = '\n'; |
|
832 }else if( c=='t' ){ |
|
833 c = '\t'; |
|
834 }else if( c=='r' ){ |
|
835 c = '\r'; |
|
836 }else if( c>='0' && c<='7' ){ |
|
837 c -= '0'; |
|
838 if( z[i+1]>='0' && z[i+1]<='7' ){ |
|
839 i++; |
|
840 c = (c<<3) + z[i] - '0'; |
|
841 if( z[i+1]>='0' && z[i+1]<='7' ){ |
|
842 i++; |
|
843 c = (c<<3) + z[i] - '0'; |
|
844 } |
|
845 } |
|
846 } |
|
847 } |
|
848 z[j] = c; |
|
849 } |
|
850 z[j] = 0; |
|
851 } |
|
852 |
|
853 /* |
|
854 ** If an input line begins with "." then invoke this routine to |
|
855 ** process that line. |
|
856 ** |
|
857 ** Return 1 to exit and 0 to continue. |
|
858 */ |
|
859 static int do_meta_command(char *zLine, struct callback_data *p){ |
|
860 int i = 1; |
|
861 int nArg = 0; |
|
862 int n, c; |
|
863 int rc = 0; |
|
864 char *azArg[50]; |
|
865 |
|
866 /* Parse the input line into tokens. |
|
867 */ |
|
868 while( zLine[i] && nArg<ArraySize(azArg) ){ |
|
869 while( isspace((unsigned char)zLine[i]) ){ i++; } |
|
870 if( zLine[i]==0 ) break; |
|
871 if( zLine[i]=='\'' || zLine[i]=='"' ){ |
|
872 int delim = zLine[i++]; |
|
873 azArg[nArg++] = &zLine[i]; |
|
874 while( zLine[i] && zLine[i]!=delim ){ i++; } |
|
875 if( zLine[i]==delim ){ |
|
876 zLine[i++] = 0; |
|
877 } |
|
878 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); |
|
879 }else{ |
|
880 azArg[nArg++] = &zLine[i]; |
|
881 while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; } |
|
882 if( zLine[i] ) zLine[i++] = 0; |
|
883 resolve_backslashes(azArg[nArg-1]); |
|
884 } |
|
885 } |
|
886 |
|
887 /* Process the input line. |
|
888 */ |
|
889 if( nArg==0 ) return rc; |
|
890 n = strlen(azArg[0]); |
|
891 c = azArg[0][0]; |
|
892 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ |
|
893 struct callback_data data; |
|
894 char *zErrMsg = 0; |
|
895 open_db(p); |
|
896 memcpy(&data, p, sizeof(data)); |
|
897 data.showHeader = 1; |
|
898 data.mode = MODE_Column; |
|
899 data.colWidth[0] = 3; |
|
900 data.colWidth[1] = 15; |
|
901 data.colWidth[2] = 58; |
|
902 data.cnt = 0; |
|
903 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); |
|
904 if( zErrMsg ){ |
|
905 fprintf(stderr,"Error: %s\n", zErrMsg); |
|
906 sqlite3_free(zErrMsg); |
|
907 } |
|
908 }else |
|
909 |
|
910 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ |
|
911 char *zErrMsg = 0; |
|
912 open_db(p); |
|
913 fprintf(p->out, "BEGIN TRANSACTION;\n"); |
|
914 if( nArg==1 ){ |
|
915 run_schema_dump_query(p, |
|
916 "SELECT name, type, sql FROM sqlite_master " |
|
917 "WHERE sql NOT NULL AND type=='table'", 0 |
|
918 ); |
|
919 run_schema_dump_query(p, |
|
920 "SELECT name, type, sql FROM sqlite_master " |
|
921 "WHERE sql NOT NULL AND type!='table' AND type!='meta'", 0 |
|
922 ); |
|
923 }else{ |
|
924 int i; |
|
925 for(i=1; i<nArg; i++){ |
|
926 zShellStatic = azArg[i]; |
|
927 run_schema_dump_query(p, |
|
928 "SELECT name, type, sql FROM sqlite_master " |
|
929 "WHERE tbl_name LIKE shellstatic() AND type=='table'" |
|
930 " AND sql NOT NULL", 0); |
|
931 run_schema_dump_query(p, |
|
932 "SELECT name, type, sql FROM sqlite_master " |
|
933 "WHERE tbl_name LIKE shellstatic() AND type!='table'" |
|
934 " AND type!='meta' AND sql NOT NULL", 0); |
|
935 zShellStatic = 0; |
|
936 } |
|
937 } |
|
938 if( zErrMsg ){ |
|
939 fprintf(stderr,"Error: %s\n", zErrMsg); |
|
940 sqlite3_free(zErrMsg); |
|
941 }else{ |
|
942 fprintf(p->out, "COMMIT;\n"); |
|
943 } |
|
944 }else |
|
945 |
|
946 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){ |
|
947 int j; |
|
948 char *z = azArg[1]; |
|
949 int val = atoi(azArg[1]); |
|
950 for(j=0; z[j]; j++){ |
|
951 z[j] = tolower((unsigned char)z[j]); |
|
952 } |
|
953 if( strcmp(z,"on")==0 ){ |
|
954 val = 1; |
|
955 }else if( strcmp(z,"yes")==0 ){ |
|
956 val = 1; |
|
957 } |
|
958 p->echoOn = val; |
|
959 }else |
|
960 |
|
961 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ |
|
962 rc = 1; |
|
963 }else |
|
964 |
|
965 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
|
966 int j; |
|
967 static char zOne[] = "1"; |
|
968 char *z = nArg>=2 ? azArg[1] : zOne; |
|
969 int val = atoi(z); |
|
970 for(j=0; z[j]; j++){ |
|
971 z[j] = tolower((unsigned char)z[j]); |
|
972 } |
|
973 if( strcmp(z,"on")==0 ){ |
|
974 val = 1; |
|
975 }else if( strcmp(z,"yes")==0 ){ |
|
976 val = 1; |
|
977 } |
|
978 if(val == 1) { |
|
979 if(!p->explainPrev.valid) { |
|
980 p->explainPrev.valid = 1; |
|
981 p->explainPrev.mode = p->mode; |
|
982 p->explainPrev.showHeader = p->showHeader; |
|
983 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); |
|
984 } |
|
985 /* We could put this code under the !p->explainValid |
|
986 ** condition so that it does not execute if we are already in |
|
987 ** explain mode. However, always executing it allows us an easy |
|
988 ** was to reset to explain mode in case the user previously |
|
989 ** did an .explain followed by a .width, .mode or .header |
|
990 ** command. |
|
991 */ |
|
992 p->mode = MODE_Column; |
|
993 p->showHeader = 1; |
|
994 memset(p->colWidth,0,ArraySize(p->colWidth)); |
|
995 p->colWidth[0] = 4; |
|
996 p->colWidth[1] = 14; |
|
997 p->colWidth[2] = 10; |
|
998 p->colWidth[3] = 10; |
|
999 p->colWidth[4] = 33; |
|
1000 }else if (p->explainPrev.valid) { |
|
1001 p->explainPrev.valid = 0; |
|
1002 p->mode = p->explainPrev.mode; |
|
1003 p->showHeader = p->explainPrev.showHeader; |
|
1004 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); |
|
1005 } |
|
1006 }else |
|
1007 |
|
1008 if( c=='h' && (strncmp(azArg[0], "header", n)==0 |
|
1009 || |
|
1010 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){ |
|
1011 int j; |
|
1012 char *z = azArg[1]; |
|
1013 int val = atoi(azArg[1]); |
|
1014 for(j=0; z[j]; j++){ |
|
1015 z[j] = tolower((unsigned char)z[j]); |
|
1016 } |
|
1017 if( strcmp(z,"on")==0 ){ |
|
1018 val = 1; |
|
1019 }else if( strcmp(z,"yes")==0 ){ |
|
1020 val = 1; |
|
1021 } |
|
1022 p->showHeader = val; |
|
1023 }else |
|
1024 |
|
1025 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ |
|
1026 fprintf(stderr,zHelp); |
|
1027 }else |
|
1028 |
|
1029 if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){ |
|
1030 char *zTable = azArg[2]; /* Insert data into this table */ |
|
1031 char *zFile = azArg[1]; /* The file from which to extract data */ |
|
1032 sqlite3_stmt *pStmt; /* A statement */ |
|
1033 int rc; /* Result code */ |
|
1034 int nCol; /* Number of columns in the table */ |
|
1035 int nByte; /* Number of bytes in an SQL string */ |
|
1036 int i, j; /* Loop counters */ |
|
1037 int nSep; /* Number of bytes in p->separator[] */ |
|
1038 char *zSql; /* An SQL statement */ |
|
1039 char *zLine; /* A single line of input from the file */ |
|
1040 char **azCol; /* zLine[] broken up into columns */ |
|
1041 char *zCommit; /* How to commit changes */ |
|
1042 FILE *in; /* The input file */ |
|
1043 int lineno = 0; /* Line number of input file */ |
|
1044 |
|
1045 open_db(p); |
|
1046 nSep = strlen(p->separator); |
|
1047 if( nSep==0 ){ |
|
1048 fprintf(stderr, "non-null separator required for import\n"); |
|
1049 return 0; |
|
1050 } |
|
1051 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); |
|
1052 if( zSql==0 ) return 0; |
|
1053 nByte = strlen(zSql); |
|
1054 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); |
|
1055 sqlite3_free(zSql); |
|
1056 if( rc ){ |
|
1057 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); |
|
1058 nCol = 0; |
|
1059 }else{ |
|
1060 nCol = sqlite3_column_count(pStmt); |
|
1061 } |
|
1062 sqlite3_finalize(pStmt); |
|
1063 if( nCol==0 ) return 0; |
|
1064 zSql = malloc( nByte + 20 + nCol*2 ); |
|
1065 if( zSql==0 ) return 0; |
|
1066 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable); |
|
1067 j = strlen(zSql); |
|
1068 for(i=1; i<nCol; i++){ |
|
1069 zSql[j++] = ','; |
|
1070 zSql[j++] = '?'; |
|
1071 } |
|
1072 zSql[j++] = ')'; |
|
1073 zSql[j] = 0; |
|
1074 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); |
|
1075 free(zSql); |
|
1076 if( rc ){ |
|
1077 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); |
|
1078 sqlite3_finalize(pStmt); |
|
1079 return 0; |
|
1080 } |
|
1081 in = fopen(zFile, "rb"); |
|
1082 if( in==0 ){ |
|
1083 fprintf(stderr, "cannot open file: %s\n", zFile); |
|
1084 sqlite3_finalize(pStmt); |
|
1085 return 0; |
|
1086 } |
|
1087 azCol = malloc( sizeof(azCol[0])*(nCol+1) ); |
|
1088 if( azCol==0 ){ |
|
1089 fclose(in); |
|
1090 return 0; |
|
1091 } |
|
1092 sqlite3_exec(p->db, "BEGIN", 0, 0, 0); |
|
1093 zCommit = "COMMIT"; |
|
1094 while( (zLine = local_getline(0, in))!=0 ){ |
|
1095 char *z; |
|
1096 i = 0; |
|
1097 lineno++; |
|
1098 azCol[0] = zLine; |
|
1099 for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){ |
|
1100 if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){ |
|
1101 *z = 0; |
|
1102 i++; |
|
1103 if( i<nCol ){ |
|
1104 azCol[i] = &z[nSep]; |
|
1105 z += nSep-1; |
|
1106 } |
|
1107 } |
|
1108 } |
|
1109 *z = 0; |
|
1110 if( i+1!=nCol ){ |
|
1111 fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n", |
|
1112 zFile, lineno, nCol, i+1); |
|
1113 zCommit = "ROLLBACK"; |
|
1114 break; |
|
1115 } |
|
1116 for(i=0; i<nCol; i++){ |
|
1117 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); |
|
1118 } |
|
1119 sqlite3_step(pStmt); |
|
1120 rc = sqlite3_reset(pStmt); |
|
1121 free(zLine); |
|
1122 if( rc!=SQLITE_OK ){ |
|
1123 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); |
|
1124 zCommit = "ROLLBACK"; |
|
1125 break; |
|
1126 } |
|
1127 } |
|
1128 free(azCol); |
|
1129 fclose(in); |
|
1130 sqlite3_finalize(pStmt); |
|
1131 sqlite3_exec(p->db, zCommit, 0, 0, 0); |
|
1132 }else |
|
1133 |
|
1134 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){ |
|
1135 struct callback_data data; |
|
1136 char *zErrMsg = 0; |
|
1137 open_db(p); |
|
1138 memcpy(&data, p, sizeof(data)); |
|
1139 data.showHeader = 0; |
|
1140 data.mode = MODE_List; |
|
1141 zShellStatic = azArg[1]; |
|
1142 sqlite3_exec(p->db, |
|
1143 "SELECT name FROM sqlite_master " |
|
1144 "WHERE type='index' AND tbl_name LIKE shellstatic() " |
|
1145 "UNION ALL " |
|
1146 "SELECT name FROM sqlite_temp_master " |
|
1147 "WHERE type='index' AND tbl_name LIKE shellstatic() " |
|
1148 "ORDER BY 1", |
|
1149 callback, &data, &zErrMsg |
|
1150 ); |
|
1151 zShellStatic = 0; |
|
1152 if( zErrMsg ){ |
|
1153 fprintf(stderr,"Error: %s\n", zErrMsg); |
|
1154 sqlite3_free(zErrMsg); |
|
1155 } |
|
1156 }else |
|
1157 |
|
1158 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
|
1159 if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ |
|
1160 const char *zFile, *zProc; |
|
1161 char *zErrMsg = 0; |
|
1162 int rc; |
|
1163 zFile = azArg[1]; |
|
1164 zProc = nArg>=3 ? azArg[2] : 0; |
|
1165 open_db(p); |
|
1166 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); |
|
1167 if( rc!=SQLITE_OK ){ |
|
1168 fprintf(stderr, "%s\n", zErrMsg); |
|
1169 sqlite3_free(zErrMsg); |
|
1170 } |
|
1171 }else |
|
1172 #endif |
|
1173 |
|
1174 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ |
|
1175 int n2 = strlen(azArg[1]); |
|
1176 if( strncmp(azArg[1],"line",n2)==0 |
|
1177 || |
|
1178 strncmp(azArg[1],"lines",n2)==0 ){ |
|
1179 p->mode = MODE_Line; |
|
1180 }else if( strncmp(azArg[1],"column",n2)==0 |
|
1181 || |
|
1182 strncmp(azArg[1],"columns",n2)==0 ){ |
|
1183 p->mode = MODE_Column; |
|
1184 }else if( strncmp(azArg[1],"list",n2)==0 ){ |
|
1185 p->mode = MODE_List; |
|
1186 }else if( strncmp(azArg[1],"html",n2)==0 ){ |
|
1187 p->mode = MODE_Html; |
|
1188 }else if( strncmp(azArg[1],"tcl",n2)==0 ){ |
|
1189 p->mode = MODE_Tcl; |
|
1190 }else if( strncmp(azArg[1],"csv",n2)==0 ){ |
|
1191 p->mode = MODE_Csv; |
|
1192 strcpy(p->separator, ","); |
|
1193 }else if( strncmp(azArg[1],"tabs",n2)==0 ){ |
|
1194 p->mode = MODE_List; |
|
1195 strcpy(p->separator, "\t"); |
|
1196 }else if( strncmp(azArg[1],"insert",n2)==0 ){ |
|
1197 p->mode = MODE_Insert; |
|
1198 if( nArg>=3 ){ |
|
1199 set_table_name(p, azArg[2]); |
|
1200 }else{ |
|
1201 set_table_name(p, "table"); |
|
1202 } |
|
1203 }else { |
|
1204 fprintf(stderr,"mode should be on of: " |
|
1205 "column csv html insert line list tabs tcl\n"); |
|
1206 } |
|
1207 }else |
|
1208 |
|
1209 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { |
|
1210 sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); |
|
1211 }else |
|
1212 |
|
1213 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ |
|
1214 if( p->out!=stdout ){ |
|
1215 fclose(p->out); |
|
1216 } |
|
1217 if( strcmp(azArg[1],"stdout")==0 ){ |
|
1218 p->out = stdout; |
|
1219 strcpy(p->outfile,"stdout"); |
|
1220 }else{ |
|
1221 p->out = fopen(azArg[1], "wb"); |
|
1222 if( p->out==0 ){ |
|
1223 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); |
|
1224 p->out = stdout; |
|
1225 } else { |
|
1226 strcpy(p->outfile,azArg[1]); |
|
1227 } |
|
1228 } |
|
1229 }else |
|
1230 |
|
1231 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ |
|
1232 if( nArg >= 2) { |
|
1233 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); |
|
1234 } |
|
1235 if( nArg >= 3) { |
|
1236 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); |
|
1237 } |
|
1238 }else |
|
1239 |
|
1240 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ |
|
1241 rc = 1; |
|
1242 }else |
|
1243 |
|
1244 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ |
|
1245 FILE *alt = fopen(azArg[1], "rb"); |
|
1246 if( alt==0 ){ |
|
1247 fprintf(stderr,"can't open \"%s\"\n", azArg[1]); |
|
1248 }else{ |
|
1249 process_input(p, alt); |
|
1250 fclose(alt); |
|
1251 } |
|
1252 }else |
|
1253 |
|
1254 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
|
1255 struct callback_data data; |
|
1256 char *zErrMsg = 0; |
|
1257 open_db(p); |
|
1258 memcpy(&data, p, sizeof(data)); |
|
1259 data.showHeader = 0; |
|
1260 data.mode = MODE_Semi; |
|
1261 if( nArg>1 ){ |
|
1262 int i; |
|
1263 for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]); |
|
1264 if( strcmp(azArg[1],"sqlite_master")==0 ){ |
|
1265 char *new_argv[2], *new_colv[2]; |
|
1266 new_argv[0] = "CREATE TABLE sqlite_master (\n" |
|
1267 " type text,\n" |
|
1268 " name text,\n" |
|
1269 " tbl_name text,\n" |
|
1270 " rootpage integer,\n" |
|
1271 " sql text\n" |
|
1272 ")"; |
|
1273 new_argv[1] = 0; |
|
1274 new_colv[0] = "sql"; |
|
1275 new_colv[1] = 0; |
|
1276 callback(&data, 1, new_argv, new_colv); |
|
1277 }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ |
|
1278 char *new_argv[2], *new_colv[2]; |
|
1279 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" |
|
1280 " type text,\n" |
|
1281 " name text,\n" |
|
1282 " tbl_name text,\n" |
|
1283 " rootpage integer,\n" |
|
1284 " sql text\n" |
|
1285 ")"; |
|
1286 new_argv[1] = 0; |
|
1287 new_colv[0] = "sql"; |
|
1288 new_colv[1] = 0; |
|
1289 callback(&data, 1, new_argv, new_colv); |
|
1290 }else{ |
|
1291 zShellStatic = azArg[1]; |
|
1292 sqlite3_exec(p->db, |
|
1293 "SELECT sql FROM " |
|
1294 " (SELECT * FROM sqlite_master UNION ALL" |
|
1295 " SELECT * FROM sqlite_temp_master) " |
|
1296 "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL " |
|
1297 "ORDER BY substr(type,2,1), name", |
|
1298 callback, &data, &zErrMsg); |
|
1299 zShellStatic = 0; |
|
1300 } |
|
1301 }else{ |
|
1302 sqlite3_exec(p->db, |
|
1303 "SELECT sql FROM " |
|
1304 " (SELECT * FROM sqlite_master UNION ALL" |
|
1305 " SELECT * FROM sqlite_temp_master) " |
|
1306 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" |
|
1307 "ORDER BY substr(type,2,1), name", |
|
1308 callback, &data, &zErrMsg |
|
1309 ); |
|
1310 } |
|
1311 if( zErrMsg ){ |
|
1312 fprintf(stderr,"Error: %s\n", zErrMsg); |
|
1313 sqlite3_free(zErrMsg); |
|
1314 } |
|
1315 }else |
|
1316 |
|
1317 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ |
|
1318 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]); |
|
1319 }else |
|
1320 |
|
1321 if( c=='s' && strncmp(azArg[0], "show", n)==0){ |
|
1322 int i; |
|
1323 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); |
|
1324 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); |
|
1325 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); |
|
1326 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); |
|
1327 fprintf(p->out,"%9.9s: ", "nullvalue"); |
|
1328 output_c_string(p->out, p->nullvalue); |
|
1329 fprintf(p->out, "\n"); |
|
1330 fprintf(p->out,"%9.9s: %s\n","output", |
|
1331 strlen(p->outfile) ? p->outfile : "stdout"); |
|
1332 fprintf(p->out,"%9.9s: ", "separator"); |
|
1333 output_c_string(p->out, p->separator); |
|
1334 fprintf(p->out, "\n"); |
|
1335 fprintf(p->out,"%9.9s: ","width"); |
|
1336 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { |
|
1337 fprintf(p->out,"%d ",p->colWidth[i]); |
|
1338 } |
|
1339 fprintf(p->out,"\n"); |
|
1340 }else |
|
1341 |
|
1342 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ |
|
1343 char **azResult; |
|
1344 int nRow, rc; |
|
1345 char *zErrMsg; |
|
1346 open_db(p); |
|
1347 if( nArg==1 ){ |
|
1348 rc = sqlite3_get_table(p->db, |
|
1349 "SELECT name FROM sqlite_master " |
|
1350 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" |
|
1351 "UNION ALL " |
|
1352 "SELECT name FROM sqlite_temp_master " |
|
1353 "WHERE type IN ('table','view') " |
|
1354 "ORDER BY 1", |
|
1355 &azResult, &nRow, 0, &zErrMsg |
|
1356 ); |
|
1357 }else{ |
|
1358 zShellStatic = azArg[1]; |
|
1359 rc = sqlite3_get_table(p->db, |
|
1360 "SELECT name FROM sqlite_master " |
|
1361 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " |
|
1362 "UNION ALL " |
|
1363 "SELECT name FROM sqlite_temp_master " |
|
1364 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " |
|
1365 "ORDER BY 1", |
|
1366 &azResult, &nRow, 0, &zErrMsg |
|
1367 ); |
|
1368 zShellStatic = 0; |
|
1369 } |
|
1370 if( zErrMsg ){ |
|
1371 fprintf(stderr,"Error: %s\n", zErrMsg); |
|
1372 sqlite3_free(zErrMsg); |
|
1373 } |
|
1374 if( rc==SQLITE_OK ){ |
|
1375 int len, maxlen = 0; |
|
1376 int i, j; |
|
1377 int nPrintCol, nPrintRow; |
|
1378 for(i=1; i<=nRow; i++){ |
|
1379 if( azResult[i]==0 ) continue; |
|
1380 len = strlen(azResult[i]); |
|
1381 if( len>maxlen ) maxlen = len; |
|
1382 } |
|
1383 nPrintCol = 80/(maxlen+2); |
|
1384 if( nPrintCol<1 ) nPrintCol = 1; |
|
1385 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; |
|
1386 for(i=0; i<nPrintRow; i++){ |
|
1387 for(j=i+1; j<=nRow; j+=nPrintRow){ |
|
1388 char *zSp = j<=nPrintRow ? "" : " "; |
|
1389 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); |
|
1390 } |
|
1391 printf("\n"); |
|
1392 } |
|
1393 } |
|
1394 sqlite3_free_table(azResult); |
|
1395 }else |
|
1396 |
|
1397 if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ |
|
1398 open_db(p); |
|
1399 sqlite3_busy_timeout(p->db, atoi(azArg[1])); |
|
1400 }else |
|
1401 |
|
1402 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ |
|
1403 int j; |
|
1404 assert( nArg<=ArraySize(azArg) ); |
|
1405 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ |
|
1406 p->colWidth[j-1] = atoi(azArg[j]); |
|
1407 } |
|
1408 }else |
|
1409 |
|
1410 { |
|
1411 fprintf(stderr, "unknown command or invalid arguments: " |
|
1412 " \"%s\". Enter \".help\" for help\n", azArg[0]); |
|
1413 } |
|
1414 |
|
1415 return rc; |
|
1416 } |
|
1417 |
|
1418 /* |
|
1419 ** Return TRUE if the last non-whitespace character in z[] is a semicolon. |
|
1420 ** z[] is N characters long. |
|
1421 */ |
|
1422 static int _ends_with_semicolon(const char *z, int N){ |
|
1423 while( N>0 && isspace((unsigned char)z[N-1]) ){ N--; } |
|
1424 return N>0 && z[N-1]==';'; |
|
1425 } |
|
1426 |
|
1427 /* |
|
1428 ** Test to see if a line consists entirely of whitespace. |
|
1429 */ |
|
1430 static int _all_whitespace(const char *z){ |
|
1431 for(; *z; z++){ |
|
1432 if( isspace(*(unsigned char*)z) ) continue; |
|
1433 if( *z=='/' && z[1]=='*' ){ |
|
1434 z += 2; |
|
1435 while( *z && (*z!='*' || z[1]!='/') ){ z++; } |
|
1436 if( *z==0 ) return 0; |
|
1437 z++; |
|
1438 continue; |
|
1439 } |
|
1440 if( *z=='-' && z[1]=='-' ){ |
|
1441 z += 2; |
|
1442 while( *z && *z!='\n' ){ z++; } |
|
1443 if( *z==0 ) return 1; |
|
1444 continue; |
|
1445 } |
|
1446 return 0; |
|
1447 } |
|
1448 return 1; |
|
1449 } |
|
1450 |
|
1451 /* |
|
1452 ** Return TRUE if the line typed in is an SQL command terminator other |
|
1453 ** than a semi-colon. The SQL Server style "go" command is understood |
|
1454 ** as is the Oracle "/". |
|
1455 */ |
|
1456 static int _is_command_terminator(const char *zLine){ |
|
1457 while( isspace(*(unsigned char*)zLine) ){ zLine++; }; |
|
1458 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */ |
|
1459 if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o' |
|
1460 && _all_whitespace(&zLine[2]) ){ |
|
1461 return 1; /* SQL Server */ |
|
1462 } |
|
1463 return 0; |
|
1464 } |
|
1465 |
|
1466 /* |
|
1467 ** Read input from *in and process it. If *in==0 then input |
|
1468 ** is interactive - the user is typing it it. Otherwise, input |
|
1469 ** is coming from a file or device. A prompt is issued and history |
|
1470 ** is saved only if input is interactive. An interrupt signal will |
|
1471 ** cause this routine to exit immediately, unless input is interactive. |
|
1472 */ |
|
1473 static void process_input(struct callback_data *p, FILE *in){ |
|
1474 char *zLine; |
|
1475 char *zSql = 0; |
|
1476 int nSql = 0; |
|
1477 char *zErrMsg; |
|
1478 int rc; |
|
1479 while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){ |
|
1480 if( seenInterrupt ){ |
|
1481 if( in!=0 ) break; |
|
1482 seenInterrupt = 0; |
|
1483 } |
|
1484 if( p->echoOn ) printf("%s\n", zLine); |
|
1485 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; |
|
1486 if( zLine && zLine[0]=='.' && nSql==0 ){ |
|
1487 int rc = do_meta_command(zLine, p); |
|
1488 free(zLine); |
|
1489 if( rc ) break; |
|
1490 continue; |
|
1491 } |
|
1492 if( _is_command_terminator(zLine) ){ |
|
1493 strcpy(zLine,";"); |
|
1494 } |
|
1495 if( zSql==0 ){ |
|
1496 int i; |
|
1497 for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){} |
|
1498 if( zLine[i]!=0 ){ |
|
1499 nSql = strlen(zLine); |
|
1500 zSql = malloc( nSql+1 ); |
|
1501 if( zSql==0 ){ |
|
1502 fprintf(stderr, "out of memory\n"); |
|
1503 exit(1); |
|
1504 } |
|
1505 strcpy(zSql, zLine); |
|
1506 } |
|
1507 }else{ |
|
1508 int len = strlen(zLine); |
|
1509 zSql = realloc( zSql, nSql + len + 2 ); |
|
1510 if( zSql==0 ){ |
|
1511 fprintf(stderr,"%s: out of memory!\n", Argv0); |
|
1512 exit(1); |
|
1513 } |
|
1514 strcpy(&zSql[nSql++], "\n"); |
|
1515 strcpy(&zSql[nSql], zLine); |
|
1516 nSql += len; |
|
1517 } |
|
1518 free(zLine); |
|
1519 if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){ |
|
1520 p->cnt = 0; |
|
1521 open_db(p); |
|
1522 rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg); |
|
1523 if( rc || zErrMsg ){ |
|
1524 /* if( in!=0 && !p->echoOn ) printf("%s\n",zSql); */ |
|
1525 if( zErrMsg!=0 ){ |
|
1526 printf("SQL error: %s\n", zErrMsg); |
|
1527 sqlite3_free(zErrMsg); |
|
1528 zErrMsg = 0; |
|
1529 }else{ |
|
1530 printf("SQL error: %s\n", sqlite3_errmsg(p->db)); |
|
1531 } |
|
1532 } |
|
1533 free(zSql); |
|
1534 zSql = 0; |
|
1535 nSql = 0; |
|
1536 } |
|
1537 } |
|
1538 if( zSql ){ |
|
1539 if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql); |
|
1540 free(zSql); |
|
1541 } |
|
1542 } |
|
1543 |
|
1544 /* |
|
1545 ** Return a pathname which is the user's home directory. A |
|
1546 ** 0 return indicates an error of some kind. Space to hold the |
|
1547 ** resulting string is obtained from malloc(). The calling |
|
1548 ** function should free the result. |
|
1549 */ |
|
1550 static char *find_home_dir(void){ |
|
1551 char *home_dir = NULL; |
|
1552 |
|
1553 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__) |
|
1554 struct passwd *pwent; |
|
1555 uid_t uid = getuid(); |
|
1556 if( (pwent=getpwuid(uid)) != NULL) { |
|
1557 home_dir = pwent->pw_dir; |
|
1558 } |
|
1559 #endif |
|
1560 |
|
1561 #ifdef __MACOS__ |
|
1562 char home_path[_MAX_PATH+1]; |
|
1563 home_dir = getcwd(home_path, _MAX_PATH); |
|
1564 #endif |
|
1565 |
|
1566 #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) |
|
1567 if (!home_dir) { |
|
1568 home_dir = getenv("USERPROFILE"); |
|
1569 } |
|
1570 #endif |
|
1571 |
|
1572 if (!home_dir) { |
|
1573 home_dir = getenv("HOME"); |
|
1574 } |
|
1575 |
|
1576 #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) |
|
1577 if (!home_dir) { |
|
1578 char *zDrive, *zPath; |
|
1579 int n; |
|
1580 zDrive = getenv("HOMEDRIVE"); |
|
1581 zPath = getenv("HOMEPATH"); |
|
1582 if( zDrive && zPath ){ |
|
1583 n = strlen(zDrive) + strlen(zPath) + 1; |
|
1584 home_dir = malloc( n ); |
|
1585 if( home_dir==0 ) return 0; |
|
1586 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); |
|
1587 return home_dir; |
|
1588 } |
|
1589 home_dir = "c:\\"; |
|
1590 } |
|
1591 #endif |
|
1592 |
|
1593 if( home_dir ){ |
|
1594 char *z = malloc( strlen(home_dir)+1 ); |
|
1595 if( z ) strcpy(z, home_dir); |
|
1596 home_dir = z; |
|
1597 } |
|
1598 |
|
1599 return home_dir; |
|
1600 } |
|
1601 |
|
1602 /* |
|
1603 ** Read input from the file given by sqliterc_override. Or if that |
|
1604 ** parameter is NULL, take input from ~/.sqliterc |
|
1605 */ |
|
1606 static void process_sqliterc( |
|
1607 struct callback_data *p, /* Configuration data */ |
|
1608 const char *sqliterc_override /* Name of config file. NULL to use default */ |
|
1609 ){ |
|
1610 char *home_dir = NULL; |
|
1611 const char *sqliterc = sqliterc_override; |
|
1612 char *zBuf = 0; |
|
1613 FILE *in = NULL; |
|
1614 |
|
1615 if (sqliterc == NULL) { |
|
1616 home_dir = find_home_dir(); |
|
1617 if( home_dir==0 ){ |
|
1618 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0); |
|
1619 return; |
|
1620 } |
|
1621 zBuf = malloc(strlen(home_dir) + 15); |
|
1622 if( zBuf==0 ){ |
|
1623 fprintf(stderr,"%s: out of memory!\n", Argv0); |
|
1624 exit(1); |
|
1625 } |
|
1626 sprintf(zBuf,"%s/.sqliterc",home_dir); |
|
1627 free(home_dir); |
|
1628 sqliterc = (const char*)zBuf; |
|
1629 } |
|
1630 in = fopen(sqliterc,"rb"); |
|
1631 if( in ){ |
|
1632 if( isatty(fileno(stdout)) ){ |
|
1633 printf("Loading resources from %s\n",sqliterc); |
|
1634 } |
|
1635 process_input(p,in); |
|
1636 fclose(in); |
|
1637 } |
|
1638 free(zBuf); |
|
1639 return; |
|
1640 } |
|
1641 |
|
1642 /* |
|
1643 ** Show available command line options |
|
1644 */ |
|
1645 static const char zOptions[] = |
|
1646 " -init filename read/process named file\n" |
|
1647 " -echo print commands before execution\n" |
|
1648 " -[no]header turn headers on or off\n" |
|
1649 " -column set output mode to 'column'\n" |
|
1650 " -html set output mode to HTML\n" |
|
1651 " -line set output mode to 'line'\n" |
|
1652 " -list set output mode to 'list'\n" |
|
1653 " -separator 'x' set output field separator (|)\n" |
|
1654 " -nullvalue 'text' set text string for NULL values\n" |
|
1655 " -version show SQLite version\n" |
|
1656 ; |
|
1657 static void usage(int showDetail){ |
|
1658 fprintf(stderr, |
|
1659 "Usage: %s [OPTIONS] FILENAME [SQL]\n" |
|
1660 "FILENAME is the name of an SQLite database. A new database is created\n" |
|
1661 "if the file does not previously exist.\n", Argv0); |
|
1662 if( showDetail ){ |
|
1663 fprintf(stderr, "OPTIONS include:\n%s", zOptions); |
|
1664 }else{ |
|
1665 fprintf(stderr, "Use the -help option for additional information\n"); |
|
1666 } |
|
1667 exit(1); |
|
1668 } |
|
1669 |
|
1670 /* |
|
1671 ** Initialize the state information in data |
|
1672 */ |
|
1673 static void main_init(struct callback_data *data) { |
|
1674 memset(data, 0, sizeof(*data)); |
|
1675 data->mode = MODE_List; |
|
1676 strcpy(data->separator,"|"); |
|
1677 data->showHeader = 0; |
|
1678 strcpy(mainPrompt,"sqlite> "); |
|
1679 strcpy(continuePrompt," ...> "); |
|
1680 } |
|
1681 |
|
1682 int main(int argc, char **argv){ |
|
1683 char *zErrMsg = 0; |
|
1684 struct callback_data data; |
|
1685 const char *zInitFile = 0; |
|
1686 char *zFirstCmd = 0; |
|
1687 int i; |
|
1688 |
|
1689 #ifdef __MACOS__ |
|
1690 argc = ccommand(&argv); |
|
1691 #endif |
|
1692 |
|
1693 Argv0 = argv[0]; |
|
1694 main_init(&data); |
|
1695 |
|
1696 /* Make sure we have a valid signal handler early, before anything |
|
1697 ** else is done. |
|
1698 */ |
|
1699 #ifdef SIGINT |
|
1700 signal(SIGINT, interrupt_handler); |
|
1701 #endif |
|
1702 |
|
1703 /* Do an initial pass through the command-line argument to locate |
|
1704 ** the name of the database file, the name of the initialization file, |
|
1705 ** and the first command to execute. |
|
1706 */ |
|
1707 for(i=1; i<argc-1; i++){ |
|
1708 if( argv[i][0]!='-' ) break; |
|
1709 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){ |
|
1710 i++; |
|
1711 }else if( strcmp(argv[i],"-init")==0 ){ |
|
1712 i++; |
|
1713 zInitFile = argv[i]; |
|
1714 }else if( strcmp(argv[i],"-key")==0 ){ |
|
1715 i++; |
|
1716 data.zKey = sqlite3_mprintf("%s",argv[i]); |
|
1717 } |
|
1718 } |
|
1719 if( i<argc ){ |
|
1720 data.zDbFilename = argv[i++]; |
|
1721 }else{ |
|
1722 #ifndef SQLITE_OMIT_MEMORYDB |
|
1723 data.zDbFilename = ":memory:"; |
|
1724 #else |
|
1725 data.zDbFilename = 0; |
|
1726 #endif |
|
1727 } |
|
1728 if( i<argc ){ |
|
1729 zFirstCmd = argv[i++]; |
|
1730 } |
|
1731 data.out = stdout; |
|
1732 |
|
1733 #ifdef SQLITE_OMIT_MEMORYDB |
|
1734 if( data.zDbFilename==0 ){ |
|
1735 fprintf(stderr,"%s: no database filename specified\n", argv[0]); |
|
1736 exit(1); |
|
1737 } |
|
1738 #endif |
|
1739 |
|
1740 /* Go ahead and open the database file if it already exists. If the |
|
1741 ** file does not exist, delay opening it. This prevents empty database |
|
1742 ** files from being created if a user mistypes the database name argument |
|
1743 ** to the sqlite command-line tool. |
|
1744 */ |
|
1745 if( access(data.zDbFilename, 0)==0 ){ |
|
1746 open_db(&data); |
|
1747 } |
|
1748 |
|
1749 /* Process the initialization file if there is one. If no -init option |
|
1750 ** is given on the command line, look for a file named ~/.sqliterc and |
|
1751 ** try to process it. |
|
1752 */ |
|
1753 process_sqliterc(&data,zInitFile); |
|
1754 |
|
1755 /* Make a second pass through the command-line argument and set |
|
1756 ** options. This second pass is delayed until after the initialization |
|
1757 ** file is processed so that the command-line arguments will override |
|
1758 ** settings in the initialization file. |
|
1759 */ |
|
1760 for(i=1; i<argc && argv[i][0]=='-'; i++){ |
|
1761 char *z = argv[i]; |
|
1762 if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){ |
|
1763 i++; |
|
1764 }else if( strcmp(z,"-html")==0 ){ |
|
1765 data.mode = MODE_Html; |
|
1766 }else if( strcmp(z,"-list")==0 ){ |
|
1767 data.mode = MODE_List; |
|
1768 }else if( strcmp(z,"-line")==0 ){ |
|
1769 data.mode = MODE_Line; |
|
1770 }else if( strcmp(z,"-column")==0 ){ |
|
1771 data.mode = MODE_Column; |
|
1772 }else if( strcmp(z,"-separator")==0 ){ |
|
1773 i++; |
|
1774 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]); |
|
1775 }else if( strcmp(z,"-nullvalue")==0 ){ |
|
1776 i++; |
|
1777 sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]); |
|
1778 }else if( strcmp(z,"-header")==0 ){ |
|
1779 data.showHeader = 1; |
|
1780 }else if( strcmp(z,"-noheader")==0 ){ |
|
1781 data.showHeader = 0; |
|
1782 }else if( strcmp(z,"-echo")==0 ){ |
|
1783 data.echoOn = 1; |
|
1784 }else if( strcmp(z,"-version")==0 ){ |
|
1785 printf("%s\n", sqlite3_libversion()); |
|
1786 return 0; |
|
1787 }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){ |
|
1788 usage(1); |
|
1789 }else{ |
|
1790 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z); |
|
1791 fprintf(stderr,"Use -help for a list of options.\n"); |
|
1792 return 1; |
|
1793 } |
|
1794 } |
|
1795 |
|
1796 if( zFirstCmd ){ |
|
1797 /* Run just the command that follows the database name |
|
1798 */ |
|
1799 if( zFirstCmd[0]=='.' ){ |
|
1800 do_meta_command(zFirstCmd, &data); |
|
1801 exit(0); |
|
1802 }else{ |
|
1803 int rc; |
|
1804 open_db(&data); |
|
1805 rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg); |
|
1806 if( rc!=0 && zErrMsg!=0 ){ |
|
1807 fprintf(stderr,"SQL error: %s\n", zErrMsg); |
|
1808 exit(1); |
|
1809 } |
|
1810 } |
|
1811 }else{ |
|
1812 /* Run commands received from standard input |
|
1813 */ |
|
1814 if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){ |
|
1815 char *zHome; |
|
1816 char *zHistory = 0; |
|
1817 printf( |
|
1818 "SQLite version %s\n" |
|
1819 "Enter \".help\" for instructions\n", |
|
1820 sqlite3_libversion() |
|
1821 ); |
|
1822 zHome = find_home_dir(); |
|
1823 if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){ |
|
1824 sprintf(zHistory,"%s/.sqlite_history", zHome); |
|
1825 } |
|
1826 #if defined(HAVE_READLINE) && HAVE_READLINE==1 |
|
1827 if( zHistory ) read_history(zHistory); |
|
1828 #endif |
|
1829 process_input(&data, 0); |
|
1830 if( zHistory ){ |
|
1831 stifle_history(100); |
|
1832 write_history(zHistory); |
|
1833 free(zHistory); |
|
1834 } |
|
1835 free(zHome); |
|
1836 }else{ |
|
1837 process_input(&data, stdin); |
|
1838 } |
|
1839 } |
|
1840 set_table_name(&data, 0); |
|
1841 if( db ){ |
|
1842 if( sqlite3_close(db)!=SQLITE_OK ){ |
|
1843 fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db)); |
|
1844 } |
|
1845 } |
|
1846 return 0; |
|
1847 } |