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