Mercurial > trustbridge > nss-cmake-static
comparison sqlite/shell.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) | |
16 /* This needs to come before any includes for MSVC compiler */ | |
17 #define _CRT_SECURE_NO_WARNINGS | |
18 #endif | |
19 | |
20 /* | |
21 ** Enable large-file support for fopen() and friends on unix. | |
22 */ | |
23 #ifndef SQLITE_DISABLE_LFS | |
24 # define _LARGE_FILE 1 | |
25 # ifndef _FILE_OFFSET_BITS | |
26 # define _FILE_OFFSET_BITS 64 | |
27 # endif | |
28 # define _LARGEFILE_SOURCE 1 | |
29 #endif | |
30 | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 #include <stdio.h> | |
34 #include <assert.h> | |
35 #include "sqlite3.h" | |
36 #include <ctype.h> | |
37 #include <stdarg.h> | |
38 | |
39 #if !defined(_WIN32) && !defined(WIN32) | |
40 # include <signal.h> | |
41 # if !defined(__RTP__) && !defined(_WRS_KERNEL) | |
42 # include <pwd.h> | |
43 # endif | |
44 # include <unistd.h> | |
45 # include <sys/types.h> | |
46 #endif | |
47 | |
48 #if defined(HAVE_READLINE) && HAVE_READLINE!=0 | |
49 # include <readline/readline.h> | |
50 # include <readline/history.h> | |
51 #else | |
52 # undef HAVE_READLINE | |
53 #endif | |
54 #if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE) | |
55 # define HAVE_READLINE 1 | |
56 # include <editline/readline.h> | |
57 #endif | |
58 #if !defined(HAVE_READLINE) | |
59 # define add_history(X) | |
60 # define read_history(X) | |
61 # define write_history(X) | |
62 # define stifle_history(X) | |
63 #endif | |
64 | |
65 #if defined(_WIN32) || defined(WIN32) | |
66 # include <io.h> | |
67 #define isatty(h) _isatty(h) | |
68 #ifndef access | |
69 # define access(f,m) _access((f),(m)) | |
70 #endif | |
71 #undef popen | |
72 #define popen _popen | |
73 #undef pclose | |
74 #define pclose _pclose | |
75 #else | |
76 /* Make sure isatty() has a prototype. | |
77 */ | |
78 extern int isatty(int); | |
79 | |
80 /* popen and pclose are not C89 functions and so are sometimes omitted from | |
81 ** the <stdio.h> header */ | |
82 extern FILE *popen(const char*,const char*); | |
83 extern int pclose(FILE*); | |
84 #endif | |
85 | |
86 #if defined(_WIN32_WCE) | |
87 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() | |
88 * thus we always assume that we have a console. That can be | |
89 * overridden with the -batch command line option. | |
90 */ | |
91 #define isatty(x) 1 | |
92 #endif | |
93 | |
94 /* ctype macros that work with signed characters */ | |
95 #define IsSpace(X) isspace((unsigned char)X) | |
96 #define IsDigit(X) isdigit((unsigned char)X) | |
97 #define ToLower(X) (char)tolower((unsigned char)X) | |
98 | |
99 | |
100 /* True if the timer is enabled */ | |
101 static int enableTimer = 0; | |
102 | |
103 /* Return the current wall-clock time */ | |
104 static sqlite3_int64 timeOfDay(void){ | |
105 static sqlite3_vfs *clockVfs = 0; | |
106 sqlite3_int64 t; | |
107 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); | |
108 if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ | |
109 clockVfs->xCurrentTimeInt64(clockVfs, &t); | |
110 }else{ | |
111 double r; | |
112 clockVfs->xCurrentTime(clockVfs, &r); | |
113 t = (sqlite3_int64)(r*86400000.0); | |
114 } | |
115 return t; | |
116 } | |
117 | |
118 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \ | |
119 && !defined(__minux) | |
120 #include <sys/time.h> | |
121 #include <sys/resource.h> | |
122 | |
123 /* Saved resource information for the beginning of an operation */ | |
124 static struct rusage sBegin; /* CPU time at start */ | |
125 static sqlite3_int64 iBegin; /* Wall-clock time at start */ | |
126 | |
127 /* | |
128 ** Begin timing an operation | |
129 */ | |
130 static void beginTimer(void){ | |
131 if( enableTimer ){ | |
132 getrusage(RUSAGE_SELF, &sBegin); | |
133 iBegin = timeOfDay(); | |
134 } | |
135 } | |
136 | |
137 /* Return the difference of two time_structs in seconds */ | |
138 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ | |
139 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + | |
140 (double)(pEnd->tv_sec - pStart->tv_sec); | |
141 } | |
142 | |
143 /* | |
144 ** Print the timing results. | |
145 */ | |
146 static void endTimer(void){ | |
147 if( enableTimer ){ | |
148 struct rusage sEnd; | |
149 sqlite3_int64 iEnd = timeOfDay(); | |
150 getrusage(RUSAGE_SELF, &sEnd); | |
151 printf("Run Time: real %.3f user %f sys %f\n", | |
152 (iEnd - iBegin)*0.001, | |
153 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), | |
154 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); | |
155 } | |
156 } | |
157 | |
158 #define BEGIN_TIMER beginTimer() | |
159 #define END_TIMER endTimer() | |
160 #define HAS_TIMER 1 | |
161 | |
162 #elif (defined(_WIN32) || defined(WIN32)) | |
163 | |
164 #include <windows.h> | |
165 | |
166 /* Saved resource information for the beginning of an operation */ | |
167 static HANDLE hProcess; | |
168 static FILETIME ftKernelBegin; | |
169 static FILETIME ftUserBegin; | |
170 static sqlite3_int64 ftWallBegin; | |
171 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME); | |
172 static GETPROCTIMES getProcessTimesAddr = NULL; | |
173 | |
174 /* | |
175 ** Check to see if we have timer support. Return 1 if necessary | |
176 ** support found (or found previously). | |
177 */ | |
178 static int hasTimer(void){ | |
179 if( getProcessTimesAddr ){ | |
180 return 1; | |
181 } else { | |
182 /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions. | |
183 ** See if the version we are running on has it, and if it does, save off | |
184 ** a pointer to it and the current process handle. | |
185 */ | |
186 hProcess = GetCurrentProcess(); | |
187 if( hProcess ){ | |
188 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); | |
189 if( NULL != hinstLib ){ | |
190 getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); | |
191 if( NULL != getProcessTimesAddr ){ | |
192 return 1; | |
193 } | |
194 FreeLibrary(hinstLib); | |
195 } | |
196 } | |
197 } | |
198 return 0; | |
199 } | |
200 | |
201 /* | |
202 ** Begin timing an operation | |
203 */ | |
204 static void beginTimer(void){ | |
205 if( enableTimer && getProcessTimesAddr ){ | |
206 FILETIME ftCreation, ftExit; | |
207 getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin); | |
208 ftWallBegin = timeOfDay(); | |
209 } | |
210 } | |
211 | |
212 /* Return the difference of two FILETIME structs in seconds */ | |
213 static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ | |
214 sqlite_int64 i64Start = *((sqlite_int64 *) pStart); | |
215 sqlite_int64 i64End = *((sqlite_int64 *) pEnd); | |
216 return (double) ((i64End - i64Start) / 10000000.0); | |
217 } | |
218 | |
219 /* | |
220 ** Print the timing results. | |
221 */ | |
222 static void endTimer(void){ | |
223 if( enableTimer && getProcessTimesAddr){ | |
224 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; | |
225 sqlite3_int64 ftWallEnd = timeOfDay(); | |
226 getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd); | |
227 printf("Run Time: real %.3f user %f sys %f\n", | |
228 (ftWallEnd - ftWallBegin)*0.001, | |
229 timeDiff(&ftUserBegin, &ftUserEnd), | |
230 timeDiff(&ftKernelBegin, &ftKernelEnd)); | |
231 } | |
232 } | |
233 | |
234 #define BEGIN_TIMER beginTimer() | |
235 #define END_TIMER endTimer() | |
236 #define HAS_TIMER hasTimer() | |
237 | |
238 #else | |
239 #define BEGIN_TIMER | |
240 #define END_TIMER | |
241 #define HAS_TIMER 0 | |
242 #endif | |
243 | |
244 /* | |
245 ** Used to prevent warnings about unused parameters | |
246 */ | |
247 #define UNUSED_PARAMETER(x) (void)(x) | |
248 | |
249 /* | |
250 ** If the following flag is set, then command execution stops | |
251 ** at an error if we are not interactive. | |
252 */ | |
253 static int bail_on_error = 0; | |
254 | |
255 /* | |
256 ** Threat stdin as an interactive input if the following variable | |
257 ** is true. Otherwise, assume stdin is connected to a file or pipe. | |
258 */ | |
259 static int stdin_is_interactive = 1; | |
260 | |
261 /* | |
262 ** The following is the open SQLite database. We make a pointer | |
263 ** to this database a static variable so that it can be accessed | |
264 ** by the SIGINT handler to interrupt database processing. | |
265 */ | |
266 static sqlite3 *db = 0; | |
267 | |
268 /* | |
269 ** True if an interrupt (Control-C) has been received. | |
270 */ | |
271 static volatile int seenInterrupt = 0; | |
272 | |
273 /* | |
274 ** This is the name of our program. It is set in main(), used | |
275 ** in a number of other places, mostly for error messages. | |
276 */ | |
277 static char *Argv0; | |
278 | |
279 /* | |
280 ** Prompt strings. Initialized in main. Settable with | |
281 ** .prompt main continue | |
282 */ | |
283 static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ | |
284 static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ | |
285 | |
286 /* | |
287 ** Write I/O traces to the following stream. | |
288 */ | |
289 #ifdef SQLITE_ENABLE_IOTRACE | |
290 static FILE *iotrace = 0; | |
291 #endif | |
292 | |
293 /* | |
294 ** This routine works like printf in that its first argument is a | |
295 ** format string and subsequent arguments are values to be substituted | |
296 ** in place of % fields. The result of formatting this string | |
297 ** is written to iotrace. | |
298 */ | |
299 #ifdef SQLITE_ENABLE_IOTRACE | |
300 static void iotracePrintf(const char *zFormat, ...){ | |
301 va_list ap; | |
302 char *z; | |
303 if( iotrace==0 ) return; | |
304 va_start(ap, zFormat); | |
305 z = sqlite3_vmprintf(zFormat, ap); | |
306 va_end(ap); | |
307 fprintf(iotrace, "%s", z); | |
308 sqlite3_free(z); | |
309 } | |
310 #endif | |
311 | |
312 | |
313 /* | |
314 ** Determines if a string is a number of not. | |
315 */ | |
316 static int isNumber(const char *z, int *realnum){ | |
317 if( *z=='-' || *z=='+' ) z++; | |
318 if( !IsDigit(*z) ){ | |
319 return 0; | |
320 } | |
321 z++; | |
322 if( realnum ) *realnum = 0; | |
323 while( IsDigit(*z) ){ z++; } | |
324 if( *z=='.' ){ | |
325 z++; | |
326 if( !IsDigit(*z) ) return 0; | |
327 while( IsDigit(*z) ){ z++; } | |
328 if( realnum ) *realnum = 1; | |
329 } | |
330 if( *z=='e' || *z=='E' ){ | |
331 z++; | |
332 if( *z=='+' || *z=='-' ) z++; | |
333 if( !IsDigit(*z) ) return 0; | |
334 while( IsDigit(*z) ){ z++; } | |
335 if( realnum ) *realnum = 1; | |
336 } | |
337 return *z==0; | |
338 } | |
339 | |
340 /* | |
341 ** A global char* and an SQL function to access its current value | |
342 ** from within an SQL statement. This program used to use the | |
343 ** sqlite_exec_printf() API to substitue a string into an SQL statement. | |
344 ** The correct way to do this with sqlite3 is to use the bind API, but | |
345 ** since the shell is built around the callback paradigm it would be a lot | |
346 ** of work. Instead just use this hack, which is quite harmless. | |
347 */ | |
348 static const char *zShellStatic = 0; | |
349 static void shellstaticFunc( | |
350 sqlite3_context *context, | |
351 int argc, | |
352 sqlite3_value **argv | |
353 ){ | |
354 assert( 0==argc ); | |
355 assert( zShellStatic ); | |
356 UNUSED_PARAMETER(argc); | |
357 UNUSED_PARAMETER(argv); | |
358 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); | |
359 } | |
360 | |
361 | |
362 /* | |
363 ** This routine reads a line of text from FILE in, stores | |
364 ** the text in memory obtained from malloc() and returns a pointer | |
365 ** to the text. NULL is returned at end of file, or if malloc() | |
366 ** fails. | |
367 ** | |
368 ** If zLine is not NULL then it is a malloced buffer returned from | |
369 ** a previous call to this routine that may be reused. | |
370 */ | |
371 static char *local_getline(char *zLine, FILE *in){ | |
372 int nLine = zLine==0 ? 0 : 100; | |
373 int n = 0; | |
374 | |
375 while( 1 ){ | |
376 if( n+100>nLine ){ | |
377 nLine = nLine*2 + 100; | |
378 zLine = realloc(zLine, nLine); | |
379 if( zLine==0 ) return 0; | |
380 } | |
381 if( fgets(&zLine[n], nLine - n, in)==0 ){ | |
382 if( n==0 ){ | |
383 free(zLine); | |
384 return 0; | |
385 } | |
386 zLine[n] = 0; | |
387 break; | |
388 } | |
389 while( zLine[n] ) n++; | |
390 if( n>0 && zLine[n-1]=='\n' ){ | |
391 n--; | |
392 if( n>0 && zLine[n-1]=='\r' ) n--; | |
393 zLine[n] = 0; | |
394 break; | |
395 } | |
396 } | |
397 return zLine; | |
398 } | |
399 | |
400 /* | |
401 ** Retrieve a single line of input text. | |
402 ** | |
403 ** If in==0 then read from standard input and prompt before each line. | |
404 ** If isContinuation is true, then a continuation prompt is appropriate. | |
405 ** If isContinuation is zero, then the main prompt should be used. | |
406 ** | |
407 ** If zPrior is not NULL then it is a buffer from a prior call to this | |
408 ** routine that can be reused. | |
409 ** | |
410 ** The result is stored in space obtained from malloc() and must either | |
411 ** be freed by the caller or else passed back into this routine via the | |
412 ** zPrior argument for reuse. | |
413 */ | |
414 static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ | |
415 char *zPrompt; | |
416 char *zResult; | |
417 if( in!=0 ){ | |
418 zResult = local_getline(zPrior, in); | |
419 }else{ | |
420 zPrompt = isContinuation ? continuePrompt : mainPrompt; | |
421 #if defined(HAVE_READLINE) | |
422 free(zPrior); | |
423 zResult = readline(zPrompt); | |
424 if( zResult && *zResult ) add_history(zResult); | |
425 #else | |
426 printf("%s", zPrompt); | |
427 fflush(stdout); | |
428 zResult = local_getline(zPrior, stdin); | |
429 #endif | |
430 } | |
431 return zResult; | |
432 } | |
433 | |
434 struct previous_mode_data { | |
435 int valid; /* Is there legit data in here? */ | |
436 int mode; | |
437 int showHeader; | |
438 int colWidth[100]; | |
439 }; | |
440 | |
441 /* | |
442 ** An pointer to an instance of this structure is passed from | |
443 ** the main program to the callback. This is used to communicate | |
444 ** state and mode information. | |
445 */ | |
446 struct callback_data { | |
447 sqlite3 *db; /* The database */ | |
448 int echoOn; /* True to echo input commands */ | |
449 int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ | |
450 int statsOn; /* True to display memory stats before each finalize */ | |
451 int outCount; /* Revert to stdout when reaching zero */ | |
452 int cnt; /* Number of records displayed so far */ | |
453 FILE *out; /* Write results here */ | |
454 FILE *traceOut; /* Output for sqlite3_trace() */ | |
455 int nErr; /* Number of errors seen */ | |
456 int mode; /* An output mode setting */ | |
457 int writableSchema; /* True if PRAGMA writable_schema=ON */ | |
458 int showHeader; /* True to show column names in List or Column mode */ | |
459 char *zDestTable; /* Name of destination table when MODE_Insert */ | |
460 char separator[20]; /* Separator character for MODE_List */ | |
461 int colWidth[100]; /* Requested width of each column when in column mode*/ | |
462 int actualWidth[100]; /* Actual width of each column */ | |
463 char nullvalue[20]; /* The text to print when a NULL comes back from | |
464 ** the database */ | |
465 struct previous_mode_data explainPrev; | |
466 /* Holds the mode information just before | |
467 ** .explain ON */ | |
468 char outfile[FILENAME_MAX]; /* Filename for *out */ | |
469 const char *zDbFilename; /* name of the database file */ | |
470 char *zFreeOnClose; /* Filename to free when closing */ | |
471 const char *zVfs; /* Name of VFS to use */ | |
472 sqlite3_stmt *pStmt; /* Current statement if any. */ | |
473 FILE *pLog; /* Write log output here */ | |
474 int *aiIndent; /* Array of indents used in MODE_Explain */ | |
475 int nIndent; /* Size of array aiIndent[] */ | |
476 int iIndent; /* Index of current op in aiIndent[] */ | |
477 }; | |
478 | |
479 /* | |
480 ** These are the allowed modes. | |
481 */ | |
482 #define MODE_Line 0 /* One column per line. Blank line between records */ | |
483 #define MODE_Column 1 /* One record per line in neat columns */ | |
484 #define MODE_List 2 /* One record per line with a separator */ | |
485 #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ | |
486 #define MODE_Html 4 /* Generate an XHTML table */ | |
487 #define MODE_Insert 5 /* Generate SQL "insert" statements */ | |
488 #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ | |
489 #define MODE_Csv 7 /* Quote strings, numbers are plain */ | |
490 #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ | |
491 | |
492 static const char *modeDescr[] = { | |
493 "line", | |
494 "column", | |
495 "list", | |
496 "semi", | |
497 "html", | |
498 "insert", | |
499 "tcl", | |
500 "csv", | |
501 "explain", | |
502 }; | |
503 | |
504 /* | |
505 ** Number of elements in an array | |
506 */ | |
507 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) | |
508 | |
509 /* | |
510 ** Compute a string length that is limited to what can be stored in | |
511 ** lower 30 bits of a 32-bit signed integer. | |
512 */ | |
513 static int strlen30(const char *z){ | |
514 const char *z2 = z; | |
515 while( *z2 ){ z2++; } | |
516 return 0x3fffffff & (int)(z2 - z); | |
517 } | |
518 | |
519 /* | |
520 ** A callback for the sqlite3_log() interface. | |
521 */ | |
522 static void shellLog(void *pArg, int iErrCode, const char *zMsg){ | |
523 struct callback_data *p = (struct callback_data*)pArg; | |
524 if( p->pLog==0 ) return; | |
525 fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); | |
526 fflush(p->pLog); | |
527 } | |
528 | |
529 /* | |
530 ** Output the given string as a hex-encoded blob (eg. X'1234' ) | |
531 */ | |
532 static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ | |
533 int i; | |
534 char *zBlob = (char *)pBlob; | |
535 fprintf(out,"X'"); | |
536 for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]&0xff); } | |
537 fprintf(out,"'"); | |
538 } | |
539 | |
540 /* | |
541 ** Output the given string as a quoted string using SQL quoting conventions. | |
542 */ | |
543 static void output_quoted_string(FILE *out, const char *z){ | |
544 int i; | |
545 int nSingle = 0; | |
546 for(i=0; z[i]; i++){ | |
547 if( z[i]=='\'' ) nSingle++; | |
548 } | |
549 if( nSingle==0 ){ | |
550 fprintf(out,"'%s'",z); | |
551 }else{ | |
552 fprintf(out,"'"); | |
553 while( *z ){ | |
554 for(i=0; z[i] && z[i]!='\''; i++){} | |
555 if( i==0 ){ | |
556 fprintf(out,"''"); | |
557 z++; | |
558 }else if( z[i]=='\'' ){ | |
559 fprintf(out,"%.*s''",i,z); | |
560 z += i+1; | |
561 }else{ | |
562 fprintf(out,"%s",z); | |
563 break; | |
564 } | |
565 } | |
566 fprintf(out,"'"); | |
567 } | |
568 } | |
569 | |
570 /* | |
571 ** Output the given string as a quoted according to C or TCL quoting rules. | |
572 */ | |
573 static void output_c_string(FILE *out, const char *z){ | |
574 unsigned int c; | |
575 fputc('"', out); | |
576 while( (c = *(z++))!=0 ){ | |
577 if( c=='\\' ){ | |
578 fputc(c, out); | |
579 fputc(c, out); | |
580 }else if( c=='"' ){ | |
581 fputc('\\', out); | |
582 fputc('"', out); | |
583 }else if( c=='\t' ){ | |
584 fputc('\\', out); | |
585 fputc('t', out); | |
586 }else if( c=='\n' ){ | |
587 fputc('\\', out); | |
588 fputc('n', out); | |
589 }else if( c=='\r' ){ | |
590 fputc('\\', out); | |
591 fputc('r', out); | |
592 }else if( !isprint(c&0xff) ){ | |
593 fprintf(out, "\\%03o", c&0xff); | |
594 }else{ | |
595 fputc(c, out); | |
596 } | |
597 } | |
598 fputc('"', out); | |
599 } | |
600 | |
601 /* | |
602 ** Output the given string with characters that are special to | |
603 ** HTML escaped. | |
604 */ | |
605 static void output_html_string(FILE *out, const char *z){ | |
606 int i; | |
607 if( z==0 ) z = ""; | |
608 while( *z ){ | |
609 for(i=0; z[i] | |
610 && z[i]!='<' | |
611 && z[i]!='&' | |
612 && z[i]!='>' | |
613 && z[i]!='\"' | |
614 && z[i]!='\''; | |
615 i++){} | |
616 if( i>0 ){ | |
617 fprintf(out,"%.*s",i,z); | |
618 } | |
619 if( z[i]=='<' ){ | |
620 fprintf(out,"<"); | |
621 }else if( z[i]=='&' ){ | |
622 fprintf(out,"&"); | |
623 }else if( z[i]=='>' ){ | |
624 fprintf(out,">"); | |
625 }else if( z[i]=='\"' ){ | |
626 fprintf(out,"""); | |
627 }else if( z[i]=='\'' ){ | |
628 fprintf(out,"'"); | |
629 }else{ | |
630 break; | |
631 } | |
632 z += i + 1; | |
633 } | |
634 } | |
635 | |
636 /* | |
637 ** If a field contains any character identified by a 1 in the following | |
638 ** array, then the string must be quoted for CSV. | |
639 */ | |
640 static const char needCsvQuote[] = { | |
641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
643 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | |
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
645 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
646 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
647 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
648 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
649 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
650 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
651 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
652 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
653 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
654 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
655 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
656 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
657 }; | |
658 | |
659 /* | |
660 ** Output a single term of CSV. Actually, p->separator is used for | |
661 ** the separator, which may or may not be a comma. p->nullvalue is | |
662 ** the null value. Strings are quoted if necessary. | |
663 */ | |
664 static void output_csv(struct callback_data *p, const char *z, int bSep){ | |
665 FILE *out = p->out; | |
666 if( z==0 ){ | |
667 fprintf(out,"%s",p->nullvalue); | |
668 }else{ | |
669 int i; | |
670 int nSep = strlen30(p->separator); | |
671 for(i=0; z[i]; i++){ | |
672 if( needCsvQuote[((unsigned char*)z)[i]] | |
673 || (z[i]==p->separator[0] && | |
674 (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ | |
675 i = 0; | |
676 break; | |
677 } | |
678 } | |
679 if( i==0 ){ | |
680 putc('"', out); | |
681 for(i=0; z[i]; i++){ | |
682 if( z[i]=='"' ) putc('"', out); | |
683 putc(z[i], out); | |
684 } | |
685 putc('"', out); | |
686 }else{ | |
687 fprintf(out, "%s", z); | |
688 } | |
689 } | |
690 if( bSep ){ | |
691 fprintf(p->out, "%s", p->separator); | |
692 } | |
693 } | |
694 | |
695 #ifdef SIGINT | |
696 /* | |
697 ** This routine runs when the user presses Ctrl-C | |
698 */ | |
699 static void interrupt_handler(int NotUsed){ | |
700 UNUSED_PARAMETER(NotUsed); | |
701 seenInterrupt++; | |
702 if( seenInterrupt>2 ) exit(1); | |
703 if( db ) sqlite3_interrupt(db); | |
704 } | |
705 #endif | |
706 | |
707 /* | |
708 ** This is the callback routine that the shell | |
709 ** invokes for each row of a query result. | |
710 */ | |
711 static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ | |
712 int i; | |
713 struct callback_data *p = (struct callback_data*)pArg; | |
714 | |
715 switch( p->mode ){ | |
716 case MODE_Line: { | |
717 int w = 5; | |
718 if( azArg==0 ) break; | |
719 for(i=0; i<nArg; i++){ | |
720 int len = strlen30(azCol[i] ? azCol[i] : ""); | |
721 if( len>w ) w = len; | |
722 } | |
723 if( p->cnt++>0 ) fprintf(p->out,"\n"); | |
724 for(i=0; i<nArg; i++){ | |
725 fprintf(p->out,"%*s = %s\n", w, azCol[i], | |
726 azArg[i] ? azArg[i] : p->nullvalue); | |
727 } | |
728 break; | |
729 } | |
730 case MODE_Explain: | |
731 case MODE_Column: { | |
732 if( p->cnt++==0 ){ | |
733 for(i=0; i<nArg; i++){ | |
734 int w, n; | |
735 if( i<ArraySize(p->colWidth) ){ | |
736 w = p->colWidth[i]; | |
737 }else{ | |
738 w = 0; | |
739 } | |
740 if( w==0 ){ | |
741 w = strlen30(azCol[i] ? azCol[i] : ""); | |
742 if( w<10 ) w = 10; | |
743 n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue); | |
744 if( w<n ) w = n; | |
745 } | |
746 if( i<ArraySize(p->actualWidth) ){ | |
747 p->actualWidth[i] = w; | |
748 } | |
749 if( p->showHeader ){ | |
750 if( w<0 ){ | |
751 fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": " "); | |
752 }else{ | |
753 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); | |
754 } | |
755 } | |
756 } | |
757 if( p->showHeader ){ | |
758 for(i=0; i<nArg; i++){ | |
759 int w; | |
760 if( i<ArraySize(p->actualWidth) ){ | |
761 w = p->actualWidth[i]; | |
762 if( w<0 ) w = -w; | |
763 }else{ | |
764 w = 10; | |
765 } | |
766 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" | |
767 "----------------------------------------------------------", | |
768 i==nArg-1 ? "\n": " "); | |
769 } | |
770 } | |
771 } | |
772 if( azArg==0 ) break; | |
773 for(i=0; i<nArg; i++){ | |
774 int w; | |
775 if( i<ArraySize(p->actualWidth) ){ | |
776 w = p->actualWidth[i]; | |
777 }else{ | |
778 w = 10; | |
779 } | |
780 if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ | |
781 w = strlen30(azArg[i]); | |
782 } | |
783 if( i==1 && p->aiIndent && p->pStmt ){ | |
784 if( p->iIndent<p->nIndent ){ | |
785 fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); | |
786 } | |
787 p->iIndent++; | |
788 } | |
789 if( w<0 ){ | |
790 fprintf(p->out,"%*.*s%s",-w,-w, | |
791 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); | |
792 }else{ | |
793 fprintf(p->out,"%-*.*s%s",w,w, | |
794 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); | |
795 } | |
796 } | |
797 break; | |
798 } | |
799 case MODE_Semi: | |
800 case MODE_List: { | |
801 if( p->cnt++==0 && p->showHeader ){ | |
802 for(i=0; i<nArg; i++){ | |
803 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); | |
804 } | |
805 } | |
806 if( azArg==0 ) break; | |
807 for(i=0; i<nArg; i++){ | |
808 char *z = azArg[i]; | |
809 if( z==0 ) z = p->nullvalue; | |
810 fprintf(p->out, "%s", z); | |
811 if( i<nArg-1 ){ | |
812 fprintf(p->out, "%s", p->separator); | |
813 }else if( p->mode==MODE_Semi ){ | |
814 fprintf(p->out, ";\n"); | |
815 }else{ | |
816 fprintf(p->out, "\n"); | |
817 } | |
818 } | |
819 break; | |
820 } | |
821 case MODE_Html: { | |
822 if( p->cnt++==0 && p->showHeader ){ | |
823 fprintf(p->out,"<TR>"); | |
824 for(i=0; i<nArg; i++){ | |
825 fprintf(p->out,"<TH>"); | |
826 output_html_string(p->out, azCol[i]); | |
827 fprintf(p->out,"</TH>\n"); | |
828 } | |
829 fprintf(p->out,"</TR>\n"); | |
830 } | |
831 if( azArg==0 ) break; | |
832 fprintf(p->out,"<TR>"); | |
833 for(i=0; i<nArg; i++){ | |
834 fprintf(p->out,"<TD>"); | |
835 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); | |
836 fprintf(p->out,"</TD>\n"); | |
837 } | |
838 fprintf(p->out,"</TR>\n"); | |
839 break; | |
840 } | |
841 case MODE_Tcl: { | |
842 if( p->cnt++==0 && p->showHeader ){ | |
843 for(i=0; i<nArg; i++){ | |
844 output_c_string(p->out,azCol[i] ? azCol[i] : ""); | |
845 if(i<nArg-1) fprintf(p->out, "%s", p->separator); | |
846 } | |
847 fprintf(p->out,"\n"); | |
848 } | |
849 if( azArg==0 ) break; | |
850 for(i=0; i<nArg; i++){ | |
851 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); | |
852 if(i<nArg-1) fprintf(p->out, "%s", p->separator); | |
853 } | |
854 fprintf(p->out,"\n"); | |
855 break; | |
856 } | |
857 case MODE_Csv: { | |
858 if( p->cnt++==0 && p->showHeader ){ | |
859 for(i=0; i<nArg; i++){ | |
860 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); | |
861 } | |
862 fprintf(p->out,"\n"); | |
863 } | |
864 if( azArg==0 ) break; | |
865 for(i=0; i<nArg; i++){ | |
866 output_csv(p, azArg[i], i<nArg-1); | |
867 } | |
868 fprintf(p->out,"\n"); | |
869 break; | |
870 } | |
871 case MODE_Insert: { | |
872 p->cnt++; | |
873 if( azArg==0 ) break; | |
874 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); | |
875 for(i=0; i<nArg; i++){ | |
876 char *zSep = i>0 ? ",": ""; | |
877 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ | |
878 fprintf(p->out,"%sNULL",zSep); | |
879 }else if( aiType && aiType[i]==SQLITE_TEXT ){ | |
880 if( zSep[0] ) fprintf(p->out,"%s",zSep); | |
881 output_quoted_string(p->out, azArg[i]); | |
882 }else if( aiType && (aiType[i]==SQLITE_INTEGER | |
883 || aiType[i]==SQLITE_FLOAT) ){ | |
884 fprintf(p->out,"%s%s",zSep, azArg[i]); | |
885 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ | |
886 const void *pBlob = sqlite3_column_blob(p->pStmt, i); | |
887 int nBlob = sqlite3_column_bytes(p->pStmt, i); | |
888 if( zSep[0] ) fprintf(p->out,"%s",zSep); | |
889 output_hex_blob(p->out, pBlob, nBlob); | |
890 }else if( isNumber(azArg[i], 0) ){ | |
891 fprintf(p->out,"%s%s",zSep, azArg[i]); | |
892 }else{ | |
893 if( zSep[0] ) fprintf(p->out,"%s",zSep); | |
894 output_quoted_string(p->out, azArg[i]); | |
895 } | |
896 } | |
897 fprintf(p->out,");\n"); | |
898 break; | |
899 } | |
900 } | |
901 return 0; | |
902 } | |
903 | |
904 /* | |
905 ** This is the callback routine that the SQLite library | |
906 ** invokes for each row of a query result. | |
907 */ | |
908 static int callback(void *pArg, int nArg, char **azArg, char **azCol){ | |
909 /* since we don't have type info, call the shell_callback with a NULL value */ | |
910 return shell_callback(pArg, nArg, azArg, azCol, NULL); | |
911 } | |
912 | |
913 /* | |
914 ** Set the destination table field of the callback_data structure to | |
915 ** the name of the table given. Escape any quote characters in the | |
916 ** table name. | |
917 */ | |
918 static void set_table_name(struct callback_data *p, const char *zName){ | |
919 int i, n; | |
920 int needQuote; | |
921 char *z; | |
922 | |
923 if( p->zDestTable ){ | |
924 free(p->zDestTable); | |
925 p->zDestTable = 0; | |
926 } | |
927 if( zName==0 ) return; | |
928 needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; | |
929 for(i=n=0; zName[i]; i++, n++){ | |
930 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ | |
931 needQuote = 1; | |
932 if( zName[i]=='\'' ) n++; | |
933 } | |
934 } | |
935 if( needQuote ) n += 2; | |
936 z = p->zDestTable = malloc( n+1 ); | |
937 if( z==0 ){ | |
938 fprintf(stderr,"Error: out of memory\n"); | |
939 exit(1); | |
940 } | |
941 n = 0; | |
942 if( needQuote ) z[n++] = '\''; | |
943 for(i=0; zName[i]; i++){ | |
944 z[n++] = zName[i]; | |
945 if( zName[i]=='\'' ) z[n++] = '\''; | |
946 } | |
947 if( needQuote ) z[n++] = '\''; | |
948 z[n] = 0; | |
949 } | |
950 | |
951 /* zIn is either a pointer to a NULL-terminated string in memory obtained | |
952 ** from malloc(), or a NULL pointer. The string pointed to by zAppend is | |
953 ** added to zIn, and the result returned in memory obtained from malloc(). | |
954 ** zIn, if it was not NULL, is freed. | |
955 ** | |
956 ** If the third argument, quote, is not '\0', then it is used as a | |
957 ** quote character for zAppend. | |
958 */ | |
959 static char *appendText(char *zIn, char const *zAppend, char quote){ | |
960 int len; | |
961 int i; | |
962 int nAppend = strlen30(zAppend); | |
963 int nIn = (zIn?strlen30(zIn):0); | |
964 | |
965 len = nAppend+nIn+1; | |
966 if( quote ){ | |
967 len += 2; | |
968 for(i=0; i<nAppend; i++){ | |
969 if( zAppend[i]==quote ) len++; | |
970 } | |
971 } | |
972 | |
973 zIn = (char *)realloc(zIn, len); | |
974 if( !zIn ){ | |
975 return 0; | |
976 } | |
977 | |
978 if( quote ){ | |
979 char *zCsr = &zIn[nIn]; | |
980 *zCsr++ = quote; | |
981 for(i=0; i<nAppend; i++){ | |
982 *zCsr++ = zAppend[i]; | |
983 if( zAppend[i]==quote ) *zCsr++ = quote; | |
984 } | |
985 *zCsr++ = quote; | |
986 *zCsr++ = '\0'; | |
987 assert( (zCsr-zIn)==len ); | |
988 }else{ | |
989 memcpy(&zIn[nIn], zAppend, nAppend); | |
990 zIn[len-1] = '\0'; | |
991 } | |
992 | |
993 return zIn; | |
994 } | |
995 | |
996 | |
997 /* | |
998 ** Execute a query statement that will generate SQL output. Print | |
999 ** the result columns, comma-separated, on a line and then add a | |
1000 ** semicolon terminator to the end of that line. | |
1001 ** | |
1002 ** If the number of columns is 1 and that column contains text "--" | |
1003 ** then write the semicolon on a separate line. That way, if a | |
1004 ** "--" comment occurs at the end of the statement, the comment | |
1005 ** won't consume the semicolon terminator. | |
1006 */ | |
1007 static int run_table_dump_query( | |
1008 struct callback_data *p, /* Query context */ | |
1009 const char *zSelect, /* SELECT statement to extract content */ | |
1010 const char *zFirstRow /* Print before first row, if not NULL */ | |
1011 ){ | |
1012 sqlite3_stmt *pSelect; | |
1013 int rc; | |
1014 int nResult; | |
1015 int i; | |
1016 const char *z; | |
1017 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); | |
1018 if( rc!=SQLITE_OK || !pSelect ){ | |
1019 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); | |
1020 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; | |
1021 return rc; | |
1022 } | |
1023 rc = sqlite3_step(pSelect); | |
1024 nResult = sqlite3_column_count(pSelect); | |
1025 while( rc==SQLITE_ROW ){ | |
1026 if( zFirstRow ){ | |
1027 fprintf(p->out, "%s", zFirstRow); | |
1028 zFirstRow = 0; | |
1029 } | |
1030 z = (const char*)sqlite3_column_text(pSelect, 0); | |
1031 fprintf(p->out, "%s", z); | |
1032 for(i=1; i<nResult; i++){ | |
1033 fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i)); | |
1034 } | |
1035 if( z==0 ) z = ""; | |
1036 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; | |
1037 if( z[0] ){ | |
1038 fprintf(p->out, "\n;\n"); | |
1039 }else{ | |
1040 fprintf(p->out, ";\n"); | |
1041 } | |
1042 rc = sqlite3_step(pSelect); | |
1043 } | |
1044 rc = sqlite3_finalize(pSelect); | |
1045 if( rc!=SQLITE_OK ){ | |
1046 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); | |
1047 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; | |
1048 } | |
1049 return rc; | |
1050 } | |
1051 | |
1052 /* | |
1053 ** Allocate space and save off current error string. | |
1054 */ | |
1055 static char *save_err_msg( | |
1056 sqlite3 *db /* Database to query */ | |
1057 ){ | |
1058 int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); | |
1059 char *zErrMsg = sqlite3_malloc(nErrMsg); | |
1060 if( zErrMsg ){ | |
1061 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); | |
1062 } | |
1063 return zErrMsg; | |
1064 } | |
1065 | |
1066 /* | |
1067 ** Display memory stats. | |
1068 */ | |
1069 static int display_stats( | |
1070 sqlite3 *db, /* Database to query */ | |
1071 struct callback_data *pArg, /* Pointer to struct callback_data */ | |
1072 int bReset /* True to reset the stats */ | |
1073 ){ | |
1074 int iCur; | |
1075 int iHiwtr; | |
1076 | |
1077 if( pArg && pArg->out ){ | |
1078 | |
1079 iHiwtr = iCur = -1; | |
1080 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); | |
1081 fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr); | |
1082 iHiwtr = iCur = -1; | |
1083 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); | |
1084 fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); | |
1085 /* | |
1086 ** Not currently used by the CLI. | |
1087 ** iHiwtr = iCur = -1; | |
1088 ** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); | |
1089 ** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); | |
1090 */ | |
1091 iHiwtr = iCur = -1; | |
1092 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); | |
1093 fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); | |
1094 /* | |
1095 ** Not currently used by the CLI. | |
1096 ** iHiwtr = iCur = -1; | |
1097 ** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); | |
1098 ** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); | |
1099 */ | |
1100 iHiwtr = iCur = -1; | |
1101 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); | |
1102 fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); | |
1103 iHiwtr = iCur = -1; | |
1104 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); | |
1105 fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr); | |
1106 iHiwtr = iCur = -1; | |
1107 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); | |
1108 fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr); | |
1109 iHiwtr = iCur = -1; | |
1110 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); | |
1111 fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr); | |
1112 #ifdef YYTRACKMAXSTACKDEPTH | |
1113 iHiwtr = iCur = -1; | |
1114 sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); | |
1115 fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr); | |
1116 #endif | |
1117 } | |
1118 | |
1119 if( pArg && pArg->out && db ){ | |
1120 iHiwtr = iCur = -1; | |
1121 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); | |
1122 fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); | |
1123 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); | |
1124 fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); | |
1125 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); | |
1126 fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); | |
1127 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); | |
1128 fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); | |
1129 iHiwtr = iCur = -1; | |
1130 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); | |
1131 fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; | |
1132 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); | |
1133 fprintf(pArg->out, "Page cache hits: %d\n", iCur); | |
1134 iHiwtr = iCur = -1; | |
1135 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); | |
1136 fprintf(pArg->out, "Page cache misses: %d\n", iCur); | |
1137 iHiwtr = iCur = -1; | |
1138 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); | |
1139 fprintf(pArg->out, "Page cache writes: %d\n", iCur); | |
1140 iHiwtr = iCur = -1; | |
1141 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); | |
1142 fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); | |
1143 iHiwtr = iCur = -1; | |
1144 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); | |
1145 fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); | |
1146 } | |
1147 | |
1148 if( pArg && pArg->out && db && pArg->pStmt ){ | |
1149 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); | |
1150 fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); | |
1151 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); | |
1152 fprintf(pArg->out, "Sort Operations: %d\n", iCur); | |
1153 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset); | |
1154 fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); | |
1155 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); | |
1156 fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); | |
1157 } | |
1158 | |
1159 return 0; | |
1160 } | |
1161 | |
1162 /* | |
1163 ** Parameter azArray points to a zero-terminated array of strings. zStr | |
1164 ** points to a single nul-terminated string. Return non-zero if zStr | |
1165 ** is equal, according to strcmp(), to any of the strings in the array. | |
1166 ** Otherwise, return zero. | |
1167 */ | |
1168 static int str_in_array(const char *zStr, const char **azArray){ | |
1169 int i; | |
1170 for(i=0; azArray[i]; i++){ | |
1171 if( 0==strcmp(zStr, azArray[i]) ) return 1; | |
1172 } | |
1173 return 0; | |
1174 } | |
1175 | |
1176 /* | |
1177 ** If compiled statement pSql appears to be an EXPLAIN statement, allocate | |
1178 ** and populate the callback_data.aiIndent[] array with the number of | |
1179 ** spaces each opcode should be indented before it is output. | |
1180 ** | |
1181 ** The indenting rules are: | |
1182 ** | |
1183 ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent | |
1184 ** all opcodes that occur between the p2 jump destination and the opcode | |
1185 ** itself by 2 spaces. | |
1186 ** | |
1187 ** * For each "Goto", if the jump destination is earlier in the program | |
1188 ** and ends on one of: | |
1189 ** Yield SeekGt SeekLt RowSetRead Rewind | |
1190 ** or if the P1 parameter is one instead of zero, | |
1191 ** then indent all opcodes between the earlier instruction | |
1192 ** and "Goto" by 2 spaces. | |
1193 */ | |
1194 static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ | |
1195 const char *zSql; /* The text of the SQL statement */ | |
1196 const char *z; /* Used to check if this is an EXPLAIN */ | |
1197 int *abYield = 0; /* True if op is an OP_Yield */ | |
1198 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ | |
1199 int iOp; /* Index of operation in p->aiIndent[] */ | |
1200 | |
1201 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", | |
1202 "NextIfOpen", "PrevIfOpen", 0 }; | |
1203 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", "Rewind", 0 }; | |
1204 const char *azGoto[] = { "Goto", 0 }; | |
1205 | |
1206 /* Try to figure out if this is really an EXPLAIN statement. If this | |
1207 ** cannot be verified, return early. */ | |
1208 zSql = sqlite3_sql(pSql); | |
1209 if( zSql==0 ) return; | |
1210 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); | |
1211 if( sqlite3_strnicmp(z, "explain", 7) ) return; | |
1212 | |
1213 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ | |
1214 int i; | |
1215 int iAddr = sqlite3_column_int(pSql, 0); | |
1216 const char *zOp = (const char*)sqlite3_column_text(pSql, 1); | |
1217 | |
1218 /* Set p2 to the P2 field of the current opcode. Then, assuming that | |
1219 ** p2 is an instruction address, set variable p2op to the index of that | |
1220 ** instruction in the aiIndent[] array. p2 and p2op may be different if | |
1221 ** the current instruction is part of a sub-program generated by an | |
1222 ** SQL trigger or foreign key. */ | |
1223 int p2 = sqlite3_column_int(pSql, 3); | |
1224 int p2op = (p2 + (iOp-iAddr)); | |
1225 | |
1226 /* Grow the p->aiIndent array as required */ | |
1227 if( iOp>=nAlloc ){ | |
1228 nAlloc += 100; | |
1229 p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int)); | |
1230 abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int)); | |
1231 } | |
1232 abYield[iOp] = str_in_array(zOp, azYield); | |
1233 p->aiIndent[iOp] = 0; | |
1234 p->nIndent = iOp+1; | |
1235 | |
1236 if( str_in_array(zOp, azNext) ){ | |
1237 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; | |
1238 } | |
1239 if( str_in_array(zOp, azGoto) && p2op<p->nIndent | |
1240 && (abYield[p2op] || sqlite3_column_int(pSql, 2)) | |
1241 ){ | |
1242 for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; | |
1243 } | |
1244 } | |
1245 | |
1246 p->iIndent = 0; | |
1247 sqlite3_free(abYield); | |
1248 sqlite3_reset(pSql); | |
1249 } | |
1250 | |
1251 /* | |
1252 ** Free the array allocated by explain_data_prepare(). | |
1253 */ | |
1254 static void explain_data_delete(struct callback_data *p){ | |
1255 sqlite3_free(p->aiIndent); | |
1256 p->aiIndent = 0; | |
1257 p->nIndent = 0; | |
1258 p->iIndent = 0; | |
1259 } | |
1260 | |
1261 /* | |
1262 ** Execute a statement or set of statements. Print | |
1263 ** any result rows/columns depending on the current mode | |
1264 ** set via the supplied callback. | |
1265 ** | |
1266 ** This is very similar to SQLite's built-in sqlite3_exec() | |
1267 ** function except it takes a slightly different callback | |
1268 ** and callback data argument. | |
1269 */ | |
1270 static int shell_exec( | |
1271 sqlite3 *db, /* An open database */ | |
1272 const char *zSql, /* SQL to be evaluated */ | |
1273 int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ | |
1274 /* (not the same as sqlite3_exec) */ | |
1275 struct callback_data *pArg, /* Pointer to struct callback_data */ | |
1276 char **pzErrMsg /* Error msg written here */ | |
1277 ){ | |
1278 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ | |
1279 int rc = SQLITE_OK; /* Return Code */ | |
1280 int rc2; | |
1281 const char *zLeftover; /* Tail of unprocessed SQL */ | |
1282 | |
1283 if( pzErrMsg ){ | |
1284 *pzErrMsg = NULL; | |
1285 } | |
1286 | |
1287 while( zSql[0] && (SQLITE_OK == rc) ){ | |
1288 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); | |
1289 if( SQLITE_OK != rc ){ | |
1290 if( pzErrMsg ){ | |
1291 *pzErrMsg = save_err_msg(db); | |
1292 } | |
1293 }else{ | |
1294 if( !pStmt ){ | |
1295 /* this happens for a comment or white-space */ | |
1296 zSql = zLeftover; | |
1297 while( IsSpace(zSql[0]) ) zSql++; | |
1298 continue; | |
1299 } | |
1300 | |
1301 /* save off the prepared statment handle and reset row count */ | |
1302 if( pArg ){ | |
1303 pArg->pStmt = pStmt; | |
1304 pArg->cnt = 0; | |
1305 } | |
1306 | |
1307 /* echo the sql statement if echo on */ | |
1308 if( pArg && pArg->echoOn ){ | |
1309 const char *zStmtSql = sqlite3_sql(pStmt); | |
1310 fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); | |
1311 } | |
1312 | |
1313 /* Show the EXPLAIN QUERY PLAN if .eqp is on */ | |
1314 if( pArg && pArg->autoEQP ){ | |
1315 sqlite3_stmt *pExplain; | |
1316 char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt)); | |
1317 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); | |
1318 if( rc==SQLITE_OK ){ | |
1319 while( sqlite3_step(pExplain)==SQLITE_ROW ){ | |
1320 fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0)); | |
1321 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); | |
1322 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); | |
1323 fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); | |
1324 } | |
1325 } | |
1326 sqlite3_finalize(pExplain); | |
1327 sqlite3_free(zEQP); | |
1328 } | |
1329 | |
1330 /* Output TESTCTRL_EXPLAIN text of requested */ | |
1331 if( pArg && pArg->mode==MODE_Explain ){ | |
1332 const char *zExplain = 0; | |
1333 sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain); | |
1334 if( zExplain && zExplain[0] ){ | |
1335 fprintf(pArg->out, "%s", zExplain); | |
1336 } | |
1337 } | |
1338 | |
1339 /* If the shell is currently in ".explain" mode, gather the extra | |
1340 ** data required to add indents to the output.*/ | |
1341 if( pArg && pArg->mode==MODE_Explain ){ | |
1342 explain_data_prepare(pArg, pStmt); | |
1343 } | |
1344 | |
1345 /* perform the first step. this will tell us if we | |
1346 ** have a result set or not and how wide it is. | |
1347 */ | |
1348 rc = sqlite3_step(pStmt); | |
1349 /* if we have a result set... */ | |
1350 if( SQLITE_ROW == rc ){ | |
1351 /* if we have a callback... */ | |
1352 if( xCallback ){ | |
1353 /* allocate space for col name ptr, value ptr, and type */ | |
1354 int nCol = sqlite3_column_count(pStmt); | |
1355 void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1); | |
1356 if( !pData ){ | |
1357 rc = SQLITE_NOMEM; | |
1358 }else{ | |
1359 char **azCols = (char **)pData; /* Names of result columns */ | |
1360 char **azVals = &azCols[nCol]; /* Results */ | |
1361 int *aiTypes = (int *)&azVals[nCol]; /* Result types */ | |
1362 int i, x; | |
1363 assert(sizeof(int) <= sizeof(char *)); | |
1364 /* save off ptrs to column names */ | |
1365 for(i=0; i<nCol; i++){ | |
1366 azCols[i] = (char *)sqlite3_column_name(pStmt, i); | |
1367 } | |
1368 do{ | |
1369 /* extract the data and data types */ | |
1370 for(i=0; i<nCol; i++){ | |
1371 aiTypes[i] = x = sqlite3_column_type(pStmt, i); | |
1372 if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){ | |
1373 azVals[i] = ""; | |
1374 }else{ | |
1375 azVals[i] = (char*)sqlite3_column_text(pStmt, i); | |
1376 } | |
1377 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ | |
1378 rc = SQLITE_NOMEM; | |
1379 break; /* from for */ | |
1380 } | |
1381 } /* end for */ | |
1382 | |
1383 /* if data and types extracted successfully... */ | |
1384 if( SQLITE_ROW == rc ){ | |
1385 /* call the supplied callback with the result row data */ | |
1386 if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){ | |
1387 rc = SQLITE_ABORT; | |
1388 }else{ | |
1389 rc = sqlite3_step(pStmt); | |
1390 } | |
1391 } | |
1392 } while( SQLITE_ROW == rc ); | |
1393 sqlite3_free(pData); | |
1394 } | |
1395 }else{ | |
1396 do{ | |
1397 rc = sqlite3_step(pStmt); | |
1398 } while( rc == SQLITE_ROW ); | |
1399 } | |
1400 } | |
1401 | |
1402 explain_data_delete(pArg); | |
1403 | |
1404 /* print usage stats if stats on */ | |
1405 if( pArg && pArg->statsOn ){ | |
1406 display_stats(db, pArg, 0); | |
1407 } | |
1408 | |
1409 /* Finalize the statement just executed. If this fails, save a | |
1410 ** copy of the error message. Otherwise, set zSql to point to the | |
1411 ** next statement to execute. */ | |
1412 rc2 = sqlite3_finalize(pStmt); | |
1413 if( rc!=SQLITE_NOMEM ) rc = rc2; | |
1414 if( rc==SQLITE_OK ){ | |
1415 zSql = zLeftover; | |
1416 while( IsSpace(zSql[0]) ) zSql++; | |
1417 }else if( pzErrMsg ){ | |
1418 *pzErrMsg = save_err_msg(db); | |
1419 } | |
1420 | |
1421 /* clear saved stmt handle */ | |
1422 if( pArg ){ | |
1423 pArg->pStmt = NULL; | |
1424 } | |
1425 } | |
1426 } /* end while */ | |
1427 | |
1428 return rc; | |
1429 } | |
1430 | |
1431 | |
1432 /* | |
1433 ** This is a different callback routine used for dumping the database. | |
1434 ** Each row received by this callback consists of a table name, | |
1435 ** the table type ("index" or "table") and SQL to create the table. | |
1436 ** This routine should print text sufficient to recreate the table. | |
1437 */ | |
1438 static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ | |
1439 int rc; | |
1440 const char *zTable; | |
1441 const char *zType; | |
1442 const char *zSql; | |
1443 const char *zPrepStmt = 0; | |
1444 struct callback_data *p = (struct callback_data *)pArg; | |
1445 | |
1446 UNUSED_PARAMETER(azCol); | |
1447 if( nArg!=3 ) return 1; | |
1448 zTable = azArg[0]; | |
1449 zType = azArg[1]; | |
1450 zSql = azArg[2]; | |
1451 | |
1452 if( strcmp(zTable, "sqlite_sequence")==0 ){ | |
1453 zPrepStmt = "DELETE FROM sqlite_sequence;\n"; | |
1454 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ | |
1455 fprintf(p->out, "ANALYZE sqlite_master;\n"); | |
1456 }else if( strncmp(zTable, "sqlite_", 7)==0 ){ | |
1457 return 0; | |
1458 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ | |
1459 char *zIns; | |
1460 if( !p->writableSchema ){ | |
1461 fprintf(p->out, "PRAGMA writable_schema=ON;\n"); | |
1462 p->writableSchema = 1; | |
1463 } | |
1464 zIns = sqlite3_mprintf( | |
1465 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" | |
1466 "VALUES('table','%q','%q',0,'%q');", | |
1467 zTable, zTable, zSql); | |
1468 fprintf(p->out, "%s\n", zIns); | |
1469 sqlite3_free(zIns); | |
1470 return 0; | |
1471 }else{ | |
1472 fprintf(p->out, "%s;\n", zSql); | |
1473 } | |
1474 | |
1475 if( strcmp(zType, "table")==0 ){ | |
1476 sqlite3_stmt *pTableInfo = 0; | |
1477 char *zSelect = 0; | |
1478 char *zTableInfo = 0; | |
1479 char *zTmp = 0; | |
1480 int nRow = 0; | |
1481 | |
1482 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); | |
1483 zTableInfo = appendText(zTableInfo, zTable, '"'); | |
1484 zTableInfo = appendText(zTableInfo, ");", 0); | |
1485 | |
1486 rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); | |
1487 free(zTableInfo); | |
1488 if( rc!=SQLITE_OK || !pTableInfo ){ | |
1489 return 1; | |
1490 } | |
1491 | |
1492 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); | |
1493 /* Always quote the table name, even if it appears to be pure ascii, | |
1494 ** in case it is a keyword. Ex: INSERT INTO "table" ... */ | |
1495 zTmp = appendText(zTmp, zTable, '"'); | |
1496 if( zTmp ){ | |
1497 zSelect = appendText(zSelect, zTmp, '\''); | |
1498 free(zTmp); | |
1499 } | |
1500 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); | |
1501 rc = sqlite3_step(pTableInfo); | |
1502 while( rc==SQLITE_ROW ){ | |
1503 const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); | |
1504 zSelect = appendText(zSelect, "quote(", 0); | |
1505 zSelect = appendText(zSelect, zText, '"'); | |
1506 rc = sqlite3_step(pTableInfo); | |
1507 if( rc==SQLITE_ROW ){ | |
1508 zSelect = appendText(zSelect, "), ", 0); | |
1509 }else{ | |
1510 zSelect = appendText(zSelect, ") ", 0); | |
1511 } | |
1512 nRow++; | |
1513 } | |
1514 rc = sqlite3_finalize(pTableInfo); | |
1515 if( rc!=SQLITE_OK || nRow==0 ){ | |
1516 free(zSelect); | |
1517 return 1; | |
1518 } | |
1519 zSelect = appendText(zSelect, "|| ')' FROM ", 0); | |
1520 zSelect = appendText(zSelect, zTable, '"'); | |
1521 | |
1522 rc = run_table_dump_query(p, zSelect, zPrepStmt); | |
1523 if( rc==SQLITE_CORRUPT ){ | |
1524 zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); | |
1525 run_table_dump_query(p, zSelect, 0); | |
1526 } | |
1527 free(zSelect); | |
1528 } | |
1529 return 0; | |
1530 } | |
1531 | |
1532 /* | |
1533 ** Run zQuery. Use dump_callback() as the callback routine so that | |
1534 ** the contents of the query are output as SQL statements. | |
1535 ** | |
1536 ** If we get a SQLITE_CORRUPT error, rerun the query after appending | |
1537 ** "ORDER BY rowid DESC" to the end. | |
1538 */ | |
1539 static int run_schema_dump_query( | |
1540 struct callback_data *p, | |
1541 const char *zQuery | |
1542 ){ | |
1543 int rc; | |
1544 char *zErr = 0; | |
1545 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); | |
1546 if( rc==SQLITE_CORRUPT ){ | |
1547 char *zQ2; | |
1548 int len = strlen30(zQuery); | |
1549 fprintf(p->out, "/****** CORRUPTION ERROR *******/\n"); | |
1550 if( zErr ){ | |
1551 fprintf(p->out, "/****** %s ******/\n", zErr); | |
1552 sqlite3_free(zErr); | |
1553 zErr = 0; | |
1554 } | |
1555 zQ2 = malloc( len+100 ); | |
1556 if( zQ2==0 ) return rc; | |
1557 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); | |
1558 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); | |
1559 if( rc ){ | |
1560 fprintf(p->out, "/****** ERROR: %s ******/\n", zErr); | |
1561 }else{ | |
1562 rc = SQLITE_CORRUPT; | |
1563 } | |
1564 sqlite3_free(zErr); | |
1565 free(zQ2); | |
1566 } | |
1567 return rc; | |
1568 } | |
1569 | |
1570 /* | |
1571 ** Text of a help message | |
1572 */ | |
1573 static char zHelp[] = | |
1574 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" | |
1575 ".bail on|off Stop after hitting an error. Default OFF\n" | |
1576 ".clone NEWDB Clone data into NEWDB from the existing database\n" | |
1577 ".databases List names and files of attached databases\n" | |
1578 ".dump ?TABLE? ... Dump the database in an SQL text format\n" | |
1579 " If TABLE specified, only dump tables matching\n" | |
1580 " LIKE pattern TABLE.\n" | |
1581 ".echo on|off Turn command echo on or off\n" | |
1582 ".exit Exit this program\n" | |
1583 ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n" | |
1584 " With no args, it turns EXPLAIN on.\n" | |
1585 ".headers on|off Turn display of headers on or off\n" | |
1586 ".help Show this message\n" | |
1587 ".import FILE TABLE Import data from FILE into TABLE\n" | |
1588 ".indices ?TABLE? Show names of all indices\n" | |
1589 " If TABLE specified, only show indices for tables\n" | |
1590 " matching LIKE pattern TABLE.\n" | |
1591 #ifdef SQLITE_ENABLE_IOTRACE | |
1592 ".iotrace FILE Enable I/O diagnostic logging to FILE\n" | |
1593 #endif | |
1594 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
1595 ".load FILE ?ENTRY? Load an extension library\n" | |
1596 #endif | |
1597 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" | |
1598 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" | |
1599 " csv Comma-separated values\n" | |
1600 " column Left-aligned columns. (See .width)\n" | |
1601 " html HTML <table> code\n" | |
1602 " insert SQL insert statements for TABLE\n" | |
1603 " line One value per line\n" | |
1604 " list Values delimited by .separator string\n" | |
1605 " tabs Tab-separated values\n" | |
1606 " tcl TCL list elements\n" | |
1607 ".nullvalue STRING Use STRING in place of NULL values\n" | |
1608 ".once FILENAME Output for the next SQL command only to FILENAME\n" | |
1609 ".open ?FILENAME? Close existing database and reopen FILENAME\n" | |
1610 ".output ?FILENAME? Send output to FILENAME or stdout\n" | |
1611 ".print STRING... Print literal STRING\n" | |
1612 ".prompt MAIN CONTINUE Replace the standard prompts\n" | |
1613 ".quit Exit this program\n" | |
1614 ".read FILENAME Execute SQL in FILENAME\n" | |
1615 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" | |
1616 ".save FILE Write in-memory database into FILE\n" | |
1617 ".schema ?TABLE? Show the CREATE statements\n" | |
1618 " If TABLE specified, only show tables matching\n" | |
1619 " LIKE pattern TABLE.\n" | |
1620 ".separator STRING Change separator used by output mode and .import\n" | |
1621 ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" | |
1622 ".show Show the current values for various settings\n" | |
1623 ".stats on|off Turn stats on or off\n" | |
1624 ".system CMD ARGS... Run CMD ARGS... in a system shell\n" | |
1625 ".tables ?TABLE? List names of tables\n" | |
1626 " If TABLE specified, only list tables matching\n" | |
1627 " LIKE pattern TABLE.\n" | |
1628 ".timeout MS Try opening locked tables for MS milliseconds\n" | |
1629 ".timer on|off Turn SQL timer on or off\n" | |
1630 ".trace FILE|off Output each SQL statement as it is run\n" | |
1631 ".vfsname ?AUX? Print the name of the VFS stack\n" | |
1632 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" | |
1633 " Negative values right-justify\n" | |
1634 ; | |
1635 | |
1636 /* Forward reference */ | |
1637 static int process_input(struct callback_data *p, FILE *in); | |
1638 | |
1639 /* | |
1640 ** Make sure the database is open. If it is not, then open it. If | |
1641 ** the database fails to open, print an error message and exit. | |
1642 */ | |
1643 static void open_db(struct callback_data *p, int keepAlive){ | |
1644 if( p->db==0 ){ | |
1645 sqlite3_initialize(); | |
1646 sqlite3_open(p->zDbFilename, &p->db); | |
1647 db = p->db; | |
1648 if( db && sqlite3_errcode(db)==SQLITE_OK ){ | |
1649 sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, | |
1650 shellstaticFunc, 0, 0); | |
1651 } | |
1652 if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ | |
1653 fprintf(stderr,"Error: unable to open database \"%s\": %s\n", | |
1654 p->zDbFilename, sqlite3_errmsg(db)); | |
1655 if( keepAlive ) return; | |
1656 exit(1); | |
1657 } | |
1658 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
1659 sqlite3_enable_load_extension(p->db, 1); | |
1660 #endif | |
1661 } | |
1662 } | |
1663 | |
1664 /* | |
1665 ** Do C-language style dequoting. | |
1666 ** | |
1667 ** \t -> tab | |
1668 ** \n -> newline | |
1669 ** \r -> carriage return | |
1670 ** \" -> " | |
1671 ** \NNN -> ascii character NNN in octal | |
1672 ** \\ -> backslash | |
1673 */ | |
1674 static void resolve_backslashes(char *z){ | |
1675 int i, j; | |
1676 char c; | |
1677 while( *z && *z!='\\' ) z++; | |
1678 for(i=j=0; (c = z[i])!=0; i++, j++){ | |
1679 if( c=='\\' ){ | |
1680 c = z[++i]; | |
1681 if( c=='n' ){ | |
1682 c = '\n'; | |
1683 }else if( c=='t' ){ | |
1684 c = '\t'; | |
1685 }else if( c=='r' ){ | |
1686 c = '\r'; | |
1687 }else if( c=='\\' ){ | |
1688 c = '\\'; | |
1689 }else if( c>='0' && c<='7' ){ | |
1690 c -= '0'; | |
1691 if( z[i+1]>='0' && z[i+1]<='7' ){ | |
1692 i++; | |
1693 c = (c<<3) + z[i] - '0'; | |
1694 if( z[i+1]>='0' && z[i+1]<='7' ){ | |
1695 i++; | |
1696 c = (c<<3) + z[i] - '0'; | |
1697 } | |
1698 } | |
1699 } | |
1700 } | |
1701 z[j] = c; | |
1702 } | |
1703 if( j<i ) z[j] = 0; | |
1704 } | |
1705 | |
1706 /* | |
1707 ** Return the value of a hexadecimal digit. Return -1 if the input | |
1708 ** is not a hex digit. | |
1709 */ | |
1710 static int hexDigitValue(char c){ | |
1711 if( c>='0' && c<='9' ) return c - '0'; | |
1712 if( c>='a' && c<='f' ) return c - 'a' + 10; | |
1713 if( c>='A' && c<='F' ) return c - 'A' + 10; | |
1714 return -1; | |
1715 } | |
1716 | |
1717 /* | |
1718 ** Interpret zArg as an integer value, possibly with suffixes. | |
1719 */ | |
1720 static sqlite3_int64 integerValue(const char *zArg){ | |
1721 sqlite3_int64 v = 0; | |
1722 static const struct { char *zSuffix; int iMult; } aMult[] = { | |
1723 { "KiB", 1024 }, | |
1724 { "MiB", 1024*1024 }, | |
1725 { "GiB", 1024*1024*1024 }, | |
1726 { "KB", 1000 }, | |
1727 { "MB", 1000000 }, | |
1728 { "GB", 1000000000 }, | |
1729 { "K", 1000 }, | |
1730 { "M", 1000000 }, | |
1731 { "G", 1000000000 }, | |
1732 }; | |
1733 int i; | |
1734 int isNeg = 0; | |
1735 if( zArg[0]=='-' ){ | |
1736 isNeg = 1; | |
1737 zArg++; | |
1738 }else if( zArg[0]=='+' ){ | |
1739 zArg++; | |
1740 } | |
1741 if( zArg[0]=='0' && zArg[1]=='x' ){ | |
1742 int x; | |
1743 zArg += 2; | |
1744 while( (x = hexDigitValue(zArg[0]))>=0 ){ | |
1745 v = (v<<4) + x; | |
1746 zArg++; | |
1747 } | |
1748 }else{ | |
1749 while( IsDigit(zArg[0]) ){ | |
1750 v = v*10 + zArg[0] - '0'; | |
1751 zArg++; | |
1752 } | |
1753 } | |
1754 for(i=0; i<ArraySize(aMult); i++){ | |
1755 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ | |
1756 v *= aMult[i].iMult; | |
1757 break; | |
1758 } | |
1759 } | |
1760 return isNeg? -v : v; | |
1761 } | |
1762 | |
1763 /* | |
1764 ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 | |
1765 ** for TRUE and FALSE. Return the integer value if appropriate. | |
1766 */ | |
1767 static int booleanValue(char *zArg){ | |
1768 int i; | |
1769 if( zArg[0]=='0' && zArg[1]=='x' ){ | |
1770 for(i=2; hexDigitValue(zArg[i])>=0; i++){} | |
1771 }else{ | |
1772 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} | |
1773 } | |
1774 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); | |
1775 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ | |
1776 return 1; | |
1777 } | |
1778 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ | |
1779 return 0; | |
1780 } | |
1781 fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", | |
1782 zArg); | |
1783 return 0; | |
1784 } | |
1785 | |
1786 /* | |
1787 ** Close an output file, assuming it is not stderr or stdout | |
1788 */ | |
1789 static void output_file_close(FILE *f){ | |
1790 if( f && f!=stdout && f!=stderr ) fclose(f); | |
1791 } | |
1792 | |
1793 /* | |
1794 ** Try to open an output file. The names "stdout" and "stderr" are | |
1795 ** recognized and do the right thing. NULL is returned if the output | |
1796 ** filename is "off". | |
1797 */ | |
1798 static FILE *output_file_open(const char *zFile){ | |
1799 FILE *f; | |
1800 if( strcmp(zFile,"stdout")==0 ){ | |
1801 f = stdout; | |
1802 }else if( strcmp(zFile, "stderr")==0 ){ | |
1803 f = stderr; | |
1804 }else if( strcmp(zFile, "off")==0 ){ | |
1805 f = 0; | |
1806 }else{ | |
1807 f = fopen(zFile, "wb"); | |
1808 if( f==0 ){ | |
1809 fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); | |
1810 } | |
1811 } | |
1812 return f; | |
1813 } | |
1814 | |
1815 /* | |
1816 ** A routine for handling output from sqlite3_trace(). | |
1817 */ | |
1818 static void sql_trace_callback(void *pArg, const char *z){ | |
1819 FILE *f = (FILE*)pArg; | |
1820 if( f ) fprintf(f, "%s\n", z); | |
1821 } | |
1822 | |
1823 /* | |
1824 ** A no-op routine that runs with the ".breakpoint" doc-command. This is | |
1825 ** a useful spot to set a debugger breakpoint. | |
1826 */ | |
1827 static void test_breakpoint(void){ | |
1828 static int nCall = 0; | |
1829 nCall++; | |
1830 } | |
1831 | |
1832 /* | |
1833 ** An object used to read a CSV file | |
1834 */ | |
1835 typedef struct CSVReader CSVReader; | |
1836 struct CSVReader { | |
1837 const char *zFile; /* Name of the input file */ | |
1838 FILE *in; /* Read the CSV text from this input stream */ | |
1839 char *z; /* Accumulated text for a field */ | |
1840 int n; /* Number of bytes in z */ | |
1841 int nAlloc; /* Space allocated for z[] */ | |
1842 int nLine; /* Current line number */ | |
1843 int cTerm; /* Character that terminated the most recent field */ | |
1844 int cSeparator; /* The separator character. (Usually ",") */ | |
1845 }; | |
1846 | |
1847 /* Append a single byte to z[] */ | |
1848 static void csv_append_char(CSVReader *p, int c){ | |
1849 if( p->n+1>=p->nAlloc ){ | |
1850 p->nAlloc += p->nAlloc + 100; | |
1851 p->z = sqlite3_realloc(p->z, p->nAlloc); | |
1852 if( p->z==0 ){ | |
1853 fprintf(stderr, "out of memory\n"); | |
1854 exit(1); | |
1855 } | |
1856 } | |
1857 p->z[p->n++] = (char)c; | |
1858 } | |
1859 | |
1860 /* Read a single field of CSV text. Compatible with rfc4180 and extended | |
1861 ** with the option of having a separator other than ",". | |
1862 ** | |
1863 ** + Input comes from p->in. | |
1864 ** + Store results in p->z of length p->n. Space to hold p->z comes | |
1865 ** from sqlite3_malloc(). | |
1866 ** + Use p->cSep as the separator. The default is ",". | |
1867 ** + Keep track of the line number in p->nLine. | |
1868 ** + Store the character that terminates the field in p->cTerm. Store | |
1869 ** EOF on end-of-file. | |
1870 ** + Report syntax errors on stderr | |
1871 */ | |
1872 static char *csv_read_one_field(CSVReader *p){ | |
1873 int c, pc, ppc; | |
1874 int cSep = p->cSeparator; | |
1875 p->n = 0; | |
1876 c = fgetc(p->in); | |
1877 if( c==EOF || seenInterrupt ){ | |
1878 p->cTerm = EOF; | |
1879 return 0; | |
1880 } | |
1881 if( c=='"' ){ | |
1882 int startLine = p->nLine; | |
1883 int cQuote = c; | |
1884 pc = ppc = 0; | |
1885 while( 1 ){ | |
1886 c = fgetc(p->in); | |
1887 if( c=='\n' ) p->nLine++; | |
1888 if( c==cQuote ){ | |
1889 if( pc==cQuote ){ | |
1890 pc = 0; | |
1891 continue; | |
1892 } | |
1893 } | |
1894 if( (c==cSep && pc==cQuote) | |
1895 || (c=='\n' && pc==cQuote) | |
1896 || (c=='\n' && pc=='\r' && ppc==cQuote) | |
1897 || (c==EOF && pc==cQuote) | |
1898 ){ | |
1899 do{ p->n--; }while( p->z[p->n]!=cQuote ); | |
1900 p->cTerm = c; | |
1901 break; | |
1902 } | |
1903 if( pc==cQuote && c!='\r' ){ | |
1904 fprintf(stderr, "%s:%d: unescaped %c character\n", | |
1905 p->zFile, p->nLine, cQuote); | |
1906 } | |
1907 if( c==EOF ){ | |
1908 fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", | |
1909 p->zFile, startLine, cQuote); | |
1910 p->cTerm = EOF; | |
1911 break; | |
1912 } | |
1913 csv_append_char(p, c); | |
1914 ppc = pc; | |
1915 pc = c; | |
1916 } | |
1917 }else{ | |
1918 while( c!=EOF && c!=cSep && c!='\n' ){ | |
1919 csv_append_char(p, c); | |
1920 c = fgetc(p->in); | |
1921 } | |
1922 if( c=='\n' ){ | |
1923 p->nLine++; | |
1924 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; | |
1925 } | |
1926 p->cTerm = c; | |
1927 } | |
1928 if( p->z ) p->z[p->n] = 0; | |
1929 return p->z; | |
1930 } | |
1931 | |
1932 /* | |
1933 ** Try to transfer data for table zTable. If an error is seen while | |
1934 ** moving forward, try to go backwards. The backwards movement won't | |
1935 ** work for WITHOUT ROWID tables. | |
1936 */ | |
1937 static void tryToCloneData( | |
1938 struct callback_data *p, | |
1939 sqlite3 *newDb, | |
1940 const char *zTable | |
1941 ){ | |
1942 sqlite3_stmt *pQuery = 0; | |
1943 sqlite3_stmt *pInsert = 0; | |
1944 char *zQuery = 0; | |
1945 char *zInsert = 0; | |
1946 int rc; | |
1947 int i, j, n; | |
1948 int nTable = (int)strlen(zTable); | |
1949 int k = 0; | |
1950 int cnt = 0; | |
1951 const int spinRate = 10000; | |
1952 | |
1953 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); | |
1954 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); | |
1955 if( rc ){ | |
1956 fprintf(stderr, "Error %d: %s on [%s]\n", | |
1957 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), | |
1958 zQuery); | |
1959 goto end_data_xfer; | |
1960 } | |
1961 n = sqlite3_column_count(pQuery); | |
1962 zInsert = sqlite3_malloc(200 + nTable + n*3); | |
1963 if( zInsert==0 ){ | |
1964 fprintf(stderr, "out of memory\n"); | |
1965 goto end_data_xfer; | |
1966 } | |
1967 sqlite3_snprintf(200+nTable,zInsert, | |
1968 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); | |
1969 i = (int)strlen(zInsert); | |
1970 for(j=1; j<n; j++){ | |
1971 memcpy(zInsert+i, ",?", 2); | |
1972 i += 2; | |
1973 } | |
1974 memcpy(zInsert+i, ");", 3); | |
1975 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0); | |
1976 if( rc ){ | |
1977 fprintf(stderr, "Error %d: %s on [%s]\n", | |
1978 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), | |
1979 zQuery); | |
1980 goto end_data_xfer; | |
1981 } | |
1982 for(k=0; k<2; k++){ | |
1983 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ | |
1984 for(i=0; i<n; i++){ | |
1985 switch( sqlite3_column_type(pQuery, i) ){ | |
1986 case SQLITE_NULL: { | |
1987 sqlite3_bind_null(pInsert, i+1); | |
1988 break; | |
1989 } | |
1990 case SQLITE_INTEGER: { | |
1991 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i)); | |
1992 break; | |
1993 } | |
1994 case SQLITE_FLOAT: { | |
1995 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i)); | |
1996 break; | |
1997 } | |
1998 case SQLITE_TEXT: { | |
1999 sqlite3_bind_text(pInsert, i+1, | |
2000 (const char*)sqlite3_column_text(pQuery,i), | |
2001 -1, SQLITE_STATIC); | |
2002 break; | |
2003 } | |
2004 case SQLITE_BLOB: { | |
2005 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i), | |
2006 sqlite3_column_bytes(pQuery,i), | |
2007 SQLITE_STATIC); | |
2008 break; | |
2009 } | |
2010 } | |
2011 } /* End for */ | |
2012 rc = sqlite3_step(pInsert); | |
2013 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ | |
2014 fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb), | |
2015 sqlite3_errmsg(newDb)); | |
2016 } | |
2017 sqlite3_reset(pInsert); | |
2018 cnt++; | |
2019 if( (cnt%spinRate)==0 ){ | |
2020 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]); | |
2021 fflush(stdout); | |
2022 } | |
2023 } /* End while */ | |
2024 if( rc==SQLITE_DONE ) break; | |
2025 sqlite3_finalize(pQuery); | |
2026 sqlite3_free(zQuery); | |
2027 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;", | |
2028 zTable); | |
2029 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); | |
2030 if( rc ){ | |
2031 fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable); | |
2032 break; | |
2033 } | |
2034 } /* End for(k=0...) */ | |
2035 | |
2036 end_data_xfer: | |
2037 sqlite3_finalize(pQuery); | |
2038 sqlite3_finalize(pInsert); | |
2039 sqlite3_free(zQuery); | |
2040 sqlite3_free(zInsert); | |
2041 } | |
2042 | |
2043 | |
2044 /* | |
2045 ** Try to transfer all rows of the schema that match zWhere. For | |
2046 ** each row, invoke xForEach() on the object defined by that row. | |
2047 ** If an error is encountered while moving forward through the | |
2048 ** sqlite_master table, try again moving backwards. | |
2049 */ | |
2050 static void tryToCloneSchema( | |
2051 struct callback_data *p, | |
2052 sqlite3 *newDb, | |
2053 const char *zWhere, | |
2054 void (*xForEach)(struct callback_data*,sqlite3*,const char*) | |
2055 ){ | |
2056 sqlite3_stmt *pQuery = 0; | |
2057 char *zQuery = 0; | |
2058 int rc; | |
2059 const unsigned char *zName; | |
2060 const unsigned char *zSql; | |
2061 char *zErrMsg = 0; | |
2062 | |
2063 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" | |
2064 " WHERE %s", zWhere); | |
2065 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); | |
2066 if( rc ){ | |
2067 fprintf(stderr, "Error: (%d) %s on [%s]\n", | |
2068 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), | |
2069 zQuery); | |
2070 goto end_schema_xfer; | |
2071 } | |
2072 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ | |
2073 zName = sqlite3_column_text(pQuery, 0); | |
2074 zSql = sqlite3_column_text(pQuery, 1); | |
2075 printf("%s... ", zName); fflush(stdout); | |
2076 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); | |
2077 if( zErrMsg ){ | |
2078 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); | |
2079 sqlite3_free(zErrMsg); | |
2080 zErrMsg = 0; | |
2081 } | |
2082 if( xForEach ){ | |
2083 xForEach(p, newDb, (const char*)zName); | |
2084 } | |
2085 printf("done\n"); | |
2086 } | |
2087 if( rc!=SQLITE_DONE ){ | |
2088 sqlite3_finalize(pQuery); | |
2089 sqlite3_free(zQuery); | |
2090 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master" | |
2091 " WHERE %s ORDER BY rowid DESC", zWhere); | |
2092 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); | |
2093 if( rc ){ | |
2094 fprintf(stderr, "Error: (%d) %s on [%s]\n", | |
2095 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), | |
2096 zQuery); | |
2097 goto end_schema_xfer; | |
2098 } | |
2099 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ | |
2100 zName = sqlite3_column_text(pQuery, 0); | |
2101 zSql = sqlite3_column_text(pQuery, 1); | |
2102 printf("%s... ", zName); fflush(stdout); | |
2103 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); | |
2104 if( zErrMsg ){ | |
2105 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); | |
2106 sqlite3_free(zErrMsg); | |
2107 zErrMsg = 0; | |
2108 } | |
2109 if( xForEach ){ | |
2110 xForEach(p, newDb, (const char*)zName); | |
2111 } | |
2112 printf("done\n"); | |
2113 } | |
2114 } | |
2115 end_schema_xfer: | |
2116 sqlite3_finalize(pQuery); | |
2117 sqlite3_free(zQuery); | |
2118 } | |
2119 | |
2120 /* | |
2121 ** Open a new database file named "zNewDb". Try to recover as much information | |
2122 ** as possible out of the main database (which might be corrupt) and write it | |
2123 ** into zNewDb. | |
2124 */ | |
2125 static void tryToClone(struct callback_data *p, const char *zNewDb){ | |
2126 int rc; | |
2127 sqlite3 *newDb = 0; | |
2128 if( access(zNewDb,0)==0 ){ | |
2129 fprintf(stderr, "File \"%s\" already exists.\n", zNewDb); | |
2130 return; | |
2131 } | |
2132 rc = sqlite3_open(zNewDb, &newDb); | |
2133 if( rc ){ | |
2134 fprintf(stderr, "Cannot create output database: %s\n", | |
2135 sqlite3_errmsg(newDb)); | |
2136 }else{ | |
2137 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); | |
2138 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); | |
2139 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); | |
2140 tryToCloneSchema(p, newDb, "type!='table'", 0); | |
2141 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); | |
2142 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); | |
2143 } | |
2144 sqlite3_close(newDb); | |
2145 } | |
2146 | |
2147 /* | |
2148 ** Change the output file back to stdout | |
2149 */ | |
2150 static void output_reset(struct callback_data *p){ | |
2151 if( p->outfile[0]=='|' ){ | |
2152 pclose(p->out); | |
2153 }else{ | |
2154 output_file_close(p->out); | |
2155 } | |
2156 p->outfile[0] = 0; | |
2157 p->out = stdout; | |
2158 } | |
2159 | |
2160 /* | |
2161 ** If an input line begins with "." then invoke this routine to | |
2162 ** process that line. | |
2163 ** | |
2164 ** Return 1 on error, 2 to exit, and 0 otherwise. | |
2165 */ | |
2166 static int do_meta_command(char *zLine, struct callback_data *p){ | |
2167 int i = 1; | |
2168 int nArg = 0; | |
2169 int n, c; | |
2170 int rc = 0; | |
2171 char *azArg[50]; | |
2172 | |
2173 /* Parse the input line into tokens. | |
2174 */ | |
2175 while( zLine[i] && nArg<ArraySize(azArg) ){ | |
2176 while( IsSpace(zLine[i]) ){ i++; } | |
2177 if( zLine[i]==0 ) break; | |
2178 if( zLine[i]=='\'' || zLine[i]=='"' ){ | |
2179 int delim = zLine[i++]; | |
2180 azArg[nArg++] = &zLine[i]; | |
2181 while( zLine[i] && zLine[i]!=delim ){ | |
2182 if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++; | |
2183 i++; | |
2184 } | |
2185 if( zLine[i]==delim ){ | |
2186 zLine[i++] = 0; | |
2187 } | |
2188 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); | |
2189 }else{ | |
2190 azArg[nArg++] = &zLine[i]; | |
2191 while( zLine[i] && !IsSpace(zLine[i]) ){ i++; } | |
2192 if( zLine[i] ) zLine[i++] = 0; | |
2193 resolve_backslashes(azArg[nArg-1]); | |
2194 } | |
2195 } | |
2196 | |
2197 /* Process the input line. | |
2198 */ | |
2199 if( nArg==0 ) return 0; /* no tokens, no error */ | |
2200 n = strlen30(azArg[0]); | |
2201 c = azArg[0][0]; | |
2202 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) | |
2203 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) | |
2204 ){ | |
2205 const char *zDestFile = 0; | |
2206 const char *zDb = 0; | |
2207 sqlite3 *pDest; | |
2208 sqlite3_backup *pBackup; | |
2209 int j; | |
2210 for(j=1; j<nArg; j++){ | |
2211 const char *z = azArg[j]; | |
2212 if( z[0]=='-' ){ | |
2213 while( z[0]=='-' ) z++; | |
2214 /* No options to process at this time */ | |
2215 { | |
2216 fprintf(stderr, "unknown option: %s\n", azArg[j]); | |
2217 return 1; | |
2218 } | |
2219 }else if( zDestFile==0 ){ | |
2220 zDestFile = azArg[j]; | |
2221 }else if( zDb==0 ){ | |
2222 zDb = zDestFile; | |
2223 zDestFile = azArg[j]; | |
2224 }else{ | |
2225 fprintf(stderr, "too many arguments to .backup\n"); | |
2226 return 1; | |
2227 } | |
2228 } | |
2229 if( zDestFile==0 ){ | |
2230 fprintf(stderr, "missing FILENAME argument on .backup\n"); | |
2231 return 1; | |
2232 } | |
2233 if( zDb==0 ) zDb = "main"; | |
2234 rc = sqlite3_open(zDestFile, &pDest); | |
2235 if( rc!=SQLITE_OK ){ | |
2236 fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile); | |
2237 sqlite3_close(pDest); | |
2238 return 1; | |
2239 } | |
2240 open_db(p, 0); | |
2241 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); | |
2242 if( pBackup==0 ){ | |
2243 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); | |
2244 sqlite3_close(pDest); | |
2245 return 1; | |
2246 } | |
2247 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} | |
2248 sqlite3_backup_finish(pBackup); | |
2249 if( rc==SQLITE_DONE ){ | |
2250 rc = 0; | |
2251 }else{ | |
2252 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); | |
2253 rc = 1; | |
2254 } | |
2255 sqlite3_close(pDest); | |
2256 }else | |
2257 | |
2258 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ | |
2259 if( nArg==2 ){ | |
2260 bail_on_error = booleanValue(azArg[1]); | |
2261 }else{ | |
2262 fprintf(stderr, "Usage: .bail on|off\n"); | |
2263 rc = 1; | |
2264 } | |
2265 }else | |
2266 | |
2267 /* The undocumented ".breakpoint" command causes a call to the no-op | |
2268 ** routine named test_breakpoint(). | |
2269 */ | |
2270 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ | |
2271 test_breakpoint(); | |
2272 }else | |
2273 | |
2274 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ | |
2275 if( nArg==2 ){ | |
2276 tryToClone(p, azArg[1]); | |
2277 }else{ | |
2278 fprintf(stderr, "Usage: .clone FILENAME\n"); | |
2279 rc = 1; | |
2280 } | |
2281 }else | |
2282 | |
2283 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ | |
2284 struct callback_data data; | |
2285 char *zErrMsg = 0; | |
2286 open_db(p, 0); | |
2287 memcpy(&data, p, sizeof(data)); | |
2288 data.showHeader = 1; | |
2289 data.mode = MODE_Column; | |
2290 data.colWidth[0] = 3; | |
2291 data.colWidth[1] = 15; | |
2292 data.colWidth[2] = 58; | |
2293 data.cnt = 0; | |
2294 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); | |
2295 if( zErrMsg ){ | |
2296 fprintf(stderr,"Error: %s\n", zErrMsg); | |
2297 sqlite3_free(zErrMsg); | |
2298 rc = 1; | |
2299 } | |
2300 }else | |
2301 | |
2302 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ | |
2303 open_db(p, 0); | |
2304 /* When playing back a "dump", the content might appear in an order | |
2305 ** which causes immediate foreign key constraints to be violated. | |
2306 ** So disable foreign-key constraint enforcement to prevent problems. */ | |
2307 if( nArg!=1 && nArg!=2 ){ | |
2308 fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); | |
2309 rc = 1; | |
2310 goto meta_command_exit; | |
2311 } | |
2312 fprintf(p->out, "PRAGMA foreign_keys=OFF;\n"); | |
2313 fprintf(p->out, "BEGIN TRANSACTION;\n"); | |
2314 p->writableSchema = 0; | |
2315 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); | |
2316 p->nErr = 0; | |
2317 if( nArg==1 ){ | |
2318 run_schema_dump_query(p, | |
2319 "SELECT name, type, sql FROM sqlite_master " | |
2320 "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" | |
2321 ); | |
2322 run_schema_dump_query(p, | |
2323 "SELECT name, type, sql FROM sqlite_master " | |
2324 "WHERE name=='sqlite_sequence'" | |
2325 ); | |
2326 run_table_dump_query(p, | |
2327 "SELECT sql FROM sqlite_master " | |
2328 "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 | |
2329 ); | |
2330 }else{ | |
2331 int i; | |
2332 for(i=1; i<nArg; i++){ | |
2333 zShellStatic = azArg[i]; | |
2334 run_schema_dump_query(p, | |
2335 "SELECT name, type, sql FROM sqlite_master " | |
2336 "WHERE tbl_name LIKE shellstatic() AND type=='table'" | |
2337 " AND sql NOT NULL"); | |
2338 run_table_dump_query(p, | |
2339 "SELECT sql FROM sqlite_master " | |
2340 "WHERE sql NOT NULL" | |
2341 " AND type IN ('index','trigger','view')" | |
2342 " AND tbl_name LIKE shellstatic()", 0 | |
2343 ); | |
2344 zShellStatic = 0; | |
2345 } | |
2346 } | |
2347 if( p->writableSchema ){ | |
2348 fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); | |
2349 p->writableSchema = 0; | |
2350 } | |
2351 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); | |
2352 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); | |
2353 fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); | |
2354 }else | |
2355 | |
2356 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ | |
2357 if( nArg==2 ){ | |
2358 p->echoOn = booleanValue(azArg[1]); | |
2359 }else{ | |
2360 fprintf(stderr, "Usage: .echo on|off\n"); | |
2361 rc = 1; | |
2362 } | |
2363 }else | |
2364 | |
2365 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ | |
2366 if( nArg==2 ){ | |
2367 p->autoEQP = booleanValue(azArg[1]); | |
2368 }else{ | |
2369 fprintf(stderr, "Usage: .eqp on|off\n"); | |
2370 rc = 1; | |
2371 } | |
2372 }else | |
2373 | |
2374 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ | |
2375 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); | |
2376 rc = 2; | |
2377 }else | |
2378 | |
2379 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ | |
2380 int val = nArg>=2 ? booleanValue(azArg[1]) : 1; | |
2381 if(val == 1) { | |
2382 if(!p->explainPrev.valid) { | |
2383 p->explainPrev.valid = 1; | |
2384 p->explainPrev.mode = p->mode; | |
2385 p->explainPrev.showHeader = p->showHeader; | |
2386 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); | |
2387 } | |
2388 /* We could put this code under the !p->explainValid | |
2389 ** condition so that it does not execute if we are already in | |
2390 ** explain mode. However, always executing it allows us an easy | |
2391 ** was to reset to explain mode in case the user previously | |
2392 ** did an .explain followed by a .width, .mode or .header | |
2393 ** command. | |
2394 */ | |
2395 p->mode = MODE_Explain; | |
2396 p->showHeader = 1; | |
2397 memset(p->colWidth,0,sizeof(p->colWidth)); | |
2398 p->colWidth[0] = 4; /* addr */ | |
2399 p->colWidth[1] = 13; /* opcode */ | |
2400 p->colWidth[2] = 4; /* P1 */ | |
2401 p->colWidth[3] = 4; /* P2 */ | |
2402 p->colWidth[4] = 4; /* P3 */ | |
2403 p->colWidth[5] = 13; /* P4 */ | |
2404 p->colWidth[6] = 2; /* P5 */ | |
2405 p->colWidth[7] = 13; /* Comment */ | |
2406 }else if (p->explainPrev.valid) { | |
2407 p->explainPrev.valid = 0; | |
2408 p->mode = p->explainPrev.mode; | |
2409 p->showHeader = p->explainPrev.showHeader; | |
2410 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); | |
2411 } | |
2412 }else | |
2413 | |
2414 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){ | |
2415 if( nArg==2 ){ | |
2416 p->showHeader = booleanValue(azArg[1]); | |
2417 }else{ | |
2418 fprintf(stderr, "Usage: .headers on|off\n"); | |
2419 rc = 1; | |
2420 } | |
2421 }else | |
2422 | |
2423 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ | |
2424 fprintf(p->out, "%s", zHelp); | |
2425 }else | |
2426 | |
2427 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ | |
2428 char *zTable; /* Insert data into this table */ | |
2429 char *zFile; /* Name of file to extra content from */ | |
2430 sqlite3_stmt *pStmt = NULL; /* A statement */ | |
2431 int nCol; /* Number of columns in the table */ | |
2432 int nByte; /* Number of bytes in an SQL string */ | |
2433 int i, j; /* Loop counters */ | |
2434 int needCommit; /* True to COMMIT or ROLLBACK at end */ | |
2435 int nSep; /* Number of bytes in p->separator[] */ | |
2436 char *zSql; /* An SQL statement */ | |
2437 CSVReader sCsv; /* Reader context */ | |
2438 int (*xCloser)(FILE*); /* Procedure to close th3 connection */ | |
2439 | |
2440 if( nArg!=3 ){ | |
2441 fprintf(stderr, "Usage: .import FILE TABLE\n"); | |
2442 goto meta_command_exit; | |
2443 } | |
2444 zFile = azArg[1]; | |
2445 zTable = azArg[2]; | |
2446 seenInterrupt = 0; | |
2447 memset(&sCsv, 0, sizeof(sCsv)); | |
2448 open_db(p, 0); | |
2449 nSep = strlen30(p->separator); | |
2450 if( nSep==0 ){ | |
2451 fprintf(stderr, "Error: non-null separator required for import\n"); | |
2452 return 1; | |
2453 } | |
2454 if( nSep>1 ){ | |
2455 fprintf(stderr, "Error: multi-character separators not allowed" | |
2456 " for import\n"); | |
2457 return 1; | |
2458 } | |
2459 sCsv.zFile = zFile; | |
2460 sCsv.nLine = 1; | |
2461 if( sCsv.zFile[0]=='|' ){ | |
2462 sCsv.in = popen(sCsv.zFile+1, "r"); | |
2463 sCsv.zFile = "<pipe>"; | |
2464 xCloser = pclose; | |
2465 }else{ | |
2466 sCsv.in = fopen(sCsv.zFile, "rb"); | |
2467 xCloser = fclose; | |
2468 } | |
2469 if( sCsv.in==0 ){ | |
2470 fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); | |
2471 return 1; | |
2472 } | |
2473 sCsv.cSeparator = p->separator[0]; | |
2474 zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); | |
2475 if( zSql==0 ){ | |
2476 fprintf(stderr, "Error: out of memory\n"); | |
2477 xCloser(sCsv.in); | |
2478 return 1; | |
2479 } | |
2480 nByte = strlen30(zSql); | |
2481 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
2482 csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */ | |
2483 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ | |
2484 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); | |
2485 char cSep = '('; | |
2486 while( csv_read_one_field(&sCsv) ){ | |
2487 zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z); | |
2488 cSep = ','; | |
2489 if( sCsv.cTerm!=sCsv.cSeparator ) break; | |
2490 } | |
2491 if( cSep=='(' ){ | |
2492 sqlite3_free(zCreate); | |
2493 sqlite3_free(sCsv.z); | |
2494 xCloser(sCsv.in); | |
2495 fprintf(stderr,"%s: empty file\n", sCsv.zFile); | |
2496 return 1; | |
2497 } | |
2498 zCreate = sqlite3_mprintf("%z\n)", zCreate); | |
2499 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); | |
2500 sqlite3_free(zCreate); | |
2501 if( rc ){ | |
2502 fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, | |
2503 sqlite3_errmsg(db)); | |
2504 sqlite3_free(sCsv.z); | |
2505 xCloser(sCsv.in); | |
2506 return 1; | |
2507 } | |
2508 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
2509 } | |
2510 sqlite3_free(zSql); | |
2511 if( rc ){ | |
2512 if (pStmt) sqlite3_finalize(pStmt); | |
2513 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); | |
2514 xCloser(sCsv.in); | |
2515 return 1; | |
2516 } | |
2517 nCol = sqlite3_column_count(pStmt); | |
2518 sqlite3_finalize(pStmt); | |
2519 pStmt = 0; | |
2520 if( nCol==0 ) return 0; /* no columns, no error */ | |
2521 zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 ); | |
2522 if( zSql==0 ){ | |
2523 fprintf(stderr, "Error: out of memory\n"); | |
2524 xCloser(sCsv.in); | |
2525 return 1; | |
2526 } | |
2527 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); | |
2528 j = strlen30(zSql); | |
2529 for(i=1; i<nCol; i++){ | |
2530 zSql[j++] = ','; | |
2531 zSql[j++] = '?'; | |
2532 } | |
2533 zSql[j++] = ')'; | |
2534 zSql[j] = 0; | |
2535 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
2536 sqlite3_free(zSql); | |
2537 if( rc ){ | |
2538 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); | |
2539 if (pStmt) sqlite3_finalize(pStmt); | |
2540 xCloser(sCsv.in); | |
2541 return 1; | |
2542 } | |
2543 needCommit = sqlite3_get_autocommit(db); | |
2544 if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0); | |
2545 do{ | |
2546 int startLine = sCsv.nLine; | |
2547 for(i=0; i<nCol; i++){ | |
2548 char *z = csv_read_one_field(&sCsv); | |
2549 if( z==0 && i==0 ) break; | |
2550 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); | |
2551 if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){ | |
2552 fprintf(stderr, "%s:%d: expected %d columns but found %d - " | |
2553 "filling the rest with NULL\n", | |
2554 sCsv.zFile, startLine, nCol, i+1); | |
2555 i++; | |
2556 while( i<nCol ){ sqlite3_bind_null(pStmt, i); i++; } | |
2557 } | |
2558 } | |
2559 if( sCsv.cTerm==sCsv.cSeparator ){ | |
2560 do{ | |
2561 csv_read_one_field(&sCsv); | |
2562 i++; | |
2563 }while( sCsv.cTerm==sCsv.cSeparator ); | |
2564 fprintf(stderr, "%s:%d: expected %d columns but found %d - " | |
2565 "extras ignored\n", | |
2566 sCsv.zFile, startLine, nCol, i); | |
2567 } | |
2568 if( i>=nCol ){ | |
2569 sqlite3_step(pStmt); | |
2570 rc = sqlite3_reset(pStmt); | |
2571 if( rc!=SQLITE_OK ){ | |
2572 fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine, | |
2573 sqlite3_errmsg(db)); | |
2574 } | |
2575 } | |
2576 }while( sCsv.cTerm!=EOF ); | |
2577 | |
2578 xCloser(sCsv.in); | |
2579 sqlite3_free(sCsv.z); | |
2580 sqlite3_finalize(pStmt); | |
2581 if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); | |
2582 }else | |
2583 | |
2584 if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ | |
2585 struct callback_data data; | |
2586 char *zErrMsg = 0; | |
2587 open_db(p, 0); | |
2588 memcpy(&data, p, sizeof(data)); | |
2589 data.showHeader = 0; | |
2590 data.mode = MODE_List; | |
2591 if( nArg==1 ){ | |
2592 rc = sqlite3_exec(p->db, | |
2593 "SELECT name FROM sqlite_master " | |
2594 "WHERE type='index' AND name NOT LIKE 'sqlite_%' " | |
2595 "UNION ALL " | |
2596 "SELECT name FROM sqlite_temp_master " | |
2597 "WHERE type='index' " | |
2598 "ORDER BY 1", | |
2599 callback, &data, &zErrMsg | |
2600 ); | |
2601 }else if( nArg==2 ){ | |
2602 zShellStatic = azArg[1]; | |
2603 rc = sqlite3_exec(p->db, | |
2604 "SELECT name FROM sqlite_master " | |
2605 "WHERE type='index' AND tbl_name LIKE shellstatic() " | |
2606 "UNION ALL " | |
2607 "SELECT name FROM sqlite_temp_master " | |
2608 "WHERE type='index' AND tbl_name LIKE shellstatic() " | |
2609 "ORDER BY 1", | |
2610 callback, &data, &zErrMsg | |
2611 ); | |
2612 zShellStatic = 0; | |
2613 }else{ | |
2614 fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n"); | |
2615 rc = 1; | |
2616 goto meta_command_exit; | |
2617 } | |
2618 if( zErrMsg ){ | |
2619 fprintf(stderr,"Error: %s\n", zErrMsg); | |
2620 sqlite3_free(zErrMsg); | |
2621 rc = 1; | |
2622 }else if( rc != SQLITE_OK ){ | |
2623 fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); | |
2624 rc = 1; | |
2625 } | |
2626 }else | |
2627 | |
2628 #ifdef SQLITE_ENABLE_IOTRACE | |
2629 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ | |
2630 extern void (*sqlite3IoTrace)(const char*, ...); | |
2631 if( iotrace && iotrace!=stdout ) fclose(iotrace); | |
2632 iotrace = 0; | |
2633 if( nArg<2 ){ | |
2634 sqlite3IoTrace = 0; | |
2635 }else if( strcmp(azArg[1], "-")==0 ){ | |
2636 sqlite3IoTrace = iotracePrintf; | |
2637 iotrace = stdout; | |
2638 }else{ | |
2639 iotrace = fopen(azArg[1], "w"); | |
2640 if( iotrace==0 ){ | |
2641 fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); | |
2642 sqlite3IoTrace = 0; | |
2643 rc = 1; | |
2644 }else{ | |
2645 sqlite3IoTrace = iotracePrintf; | |
2646 } | |
2647 } | |
2648 }else | |
2649 #endif | |
2650 | |
2651 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
2652 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ | |
2653 const char *zFile, *zProc; | |
2654 char *zErrMsg = 0; | |
2655 if( nArg<2 ){ | |
2656 fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); | |
2657 rc = 1; | |
2658 goto meta_command_exit; | |
2659 } | |
2660 zFile = azArg[1]; | |
2661 zProc = nArg>=3 ? azArg[2] : 0; | |
2662 open_db(p, 0); | |
2663 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); | |
2664 if( rc!=SQLITE_OK ){ | |
2665 fprintf(stderr, "Error: %s\n", zErrMsg); | |
2666 sqlite3_free(zErrMsg); | |
2667 rc = 1; | |
2668 } | |
2669 }else | |
2670 #endif | |
2671 | |
2672 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ | |
2673 if( nArg!=2 ){ | |
2674 fprintf(stderr, "Usage: .log FILENAME\n"); | |
2675 rc = 1; | |
2676 }else{ | |
2677 const char *zFile = azArg[1]; | |
2678 output_file_close(p->pLog); | |
2679 p->pLog = output_file_open(zFile); | |
2680 } | |
2681 }else | |
2682 | |
2683 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ | |
2684 const char *zMode = nArg>=2 ? azArg[1] : ""; | |
2685 int n2 = (int)strlen(zMode); | |
2686 int c2 = zMode[0]; | |
2687 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ | |
2688 p->mode = MODE_Line; | |
2689 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ | |
2690 p->mode = MODE_Column; | |
2691 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ | |
2692 p->mode = MODE_List; | |
2693 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ | |
2694 p->mode = MODE_Html; | |
2695 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ | |
2696 p->mode = MODE_Tcl; | |
2697 sqlite3_snprintf(sizeof(p->separator), p->separator, " "); | |
2698 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ | |
2699 p->mode = MODE_Csv; | |
2700 sqlite3_snprintf(sizeof(p->separator), p->separator, ","); | |
2701 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ | |
2702 p->mode = MODE_List; | |
2703 sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); | |
2704 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ | |
2705 p->mode = MODE_Insert; | |
2706 set_table_name(p, nArg>=3 ? azArg[2] : "table"); | |
2707 }else { | |
2708 fprintf(stderr,"Error: mode should be one of: " | |
2709 "column csv html insert line list tabs tcl\n"); | |
2710 rc = 1; | |
2711 } | |
2712 }else | |
2713 | |
2714 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ | |
2715 if( nArg==2 ){ | |
2716 sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, | |
2717 "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); | |
2718 }else{ | |
2719 fprintf(stderr, "Usage: .nullvalue STRING\n"); | |
2720 rc = 1; | |
2721 } | |
2722 }else | |
2723 | |
2724 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ | |
2725 sqlite3 *savedDb = p->db; | |
2726 const char *zSavedFilename = p->zDbFilename; | |
2727 char *zNewFilename = 0; | |
2728 p->db = 0; | |
2729 if( nArg>=2 ){ | |
2730 p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]); | |
2731 } | |
2732 open_db(p, 1); | |
2733 if( p->db!=0 ){ | |
2734 sqlite3_close(savedDb); | |
2735 sqlite3_free(p->zFreeOnClose); | |
2736 p->zFreeOnClose = zNewFilename; | |
2737 }else{ | |
2738 sqlite3_free(zNewFilename); | |
2739 p->db = savedDb; | |
2740 p->zDbFilename = zSavedFilename; | |
2741 } | |
2742 }else | |
2743 | |
2744 if( c=='o' | |
2745 && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0) | |
2746 ){ | |
2747 const char *zFile = nArg>=2 ? azArg[1] : "stdout"; | |
2748 if( nArg>2 ){ | |
2749 fprintf(stderr, "Usage: .%s FILE\n", azArg[0]); | |
2750 rc = 1; | |
2751 goto meta_command_exit; | |
2752 } | |
2753 if( n>1 && strncmp(azArg[0], "once", n)==0 ){ | |
2754 if( nArg<2 ){ | |
2755 fprintf(stderr, "Usage: .once FILE\n"); | |
2756 rc = 1; | |
2757 goto meta_command_exit; | |
2758 } | |
2759 p->outCount = 2; | |
2760 }else{ | |
2761 p->outCount = 0; | |
2762 } | |
2763 output_reset(p); | |
2764 if( zFile[0]=='|' ){ | |
2765 p->out = popen(zFile + 1, "w"); | |
2766 if( p->out==0 ){ | |
2767 fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); | |
2768 p->out = stdout; | |
2769 rc = 1; | |
2770 }else{ | |
2771 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); | |
2772 } | |
2773 }else{ | |
2774 p->out = output_file_open(zFile); | |
2775 if( p->out==0 ){ | |
2776 if( strcmp(zFile,"off")!=0 ){ | |
2777 fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile); | |
2778 } | |
2779 p->out = stdout; | |
2780 rc = 1; | |
2781 } else { | |
2782 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); | |
2783 } | |
2784 } | |
2785 }else | |
2786 | |
2787 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ | |
2788 int i; | |
2789 for(i=1; i<nArg; i++){ | |
2790 if( i>1 ) fprintf(p->out, " "); | |
2791 fprintf(p->out, "%s", azArg[i]); | |
2792 } | |
2793 fprintf(p->out, "\n"); | |
2794 }else | |
2795 | |
2796 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){ | |
2797 if( nArg >= 2) { | |
2798 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); | |
2799 } | |
2800 if( nArg >= 3) { | |
2801 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); | |
2802 } | |
2803 }else | |
2804 | |
2805 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ | |
2806 rc = 2; | |
2807 }else | |
2808 | |
2809 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){ | |
2810 FILE *alt; | |
2811 if( nArg!=2 ){ | |
2812 fprintf(stderr, "Usage: .read FILE\n"); | |
2813 rc = 1; | |
2814 goto meta_command_exit; | |
2815 } | |
2816 alt = fopen(azArg[1], "rb"); | |
2817 if( alt==0 ){ | |
2818 fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); | |
2819 rc = 1; | |
2820 }else{ | |
2821 rc = process_input(p, alt); | |
2822 fclose(alt); | |
2823 } | |
2824 }else | |
2825 | |
2826 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){ | |
2827 const char *zSrcFile; | |
2828 const char *zDb; | |
2829 sqlite3 *pSrc; | |
2830 sqlite3_backup *pBackup; | |
2831 int nTimeout = 0; | |
2832 | |
2833 if( nArg==2 ){ | |
2834 zSrcFile = azArg[1]; | |
2835 zDb = "main"; | |
2836 }else if( nArg==3 ){ | |
2837 zSrcFile = azArg[2]; | |
2838 zDb = azArg[1]; | |
2839 }else{ | |
2840 fprintf(stderr, "Usage: .restore ?DB? FILE\n"); | |
2841 rc = 1; | |
2842 goto meta_command_exit; | |
2843 } | |
2844 rc = sqlite3_open(zSrcFile, &pSrc); | |
2845 if( rc!=SQLITE_OK ){ | |
2846 fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); | |
2847 sqlite3_close(pSrc); | |
2848 return 1; | |
2849 } | |
2850 open_db(p, 0); | |
2851 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); | |
2852 if( pBackup==0 ){ | |
2853 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); | |
2854 sqlite3_close(pSrc); | |
2855 return 1; | |
2856 } | |
2857 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK | |
2858 || rc==SQLITE_BUSY ){ | |
2859 if( rc==SQLITE_BUSY ){ | |
2860 if( nTimeout++ >= 3 ) break; | |
2861 sqlite3_sleep(100); | |
2862 } | |
2863 } | |
2864 sqlite3_backup_finish(pBackup); | |
2865 if( rc==SQLITE_DONE ){ | |
2866 rc = 0; | |
2867 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ | |
2868 fprintf(stderr, "Error: source database is busy\n"); | |
2869 rc = 1; | |
2870 }else{ | |
2871 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); | |
2872 rc = 1; | |
2873 } | |
2874 sqlite3_close(pSrc); | |
2875 }else | |
2876 | |
2877 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ | |
2878 struct callback_data data; | |
2879 char *zErrMsg = 0; | |
2880 open_db(p, 0); | |
2881 memcpy(&data, p, sizeof(data)); | |
2882 data.showHeader = 0; | |
2883 data.mode = MODE_Semi; | |
2884 if( nArg==2 ){ | |
2885 int i; | |
2886 for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); | |
2887 if( strcmp(azArg[1],"sqlite_master")==0 ){ | |
2888 char *new_argv[2], *new_colv[2]; | |
2889 new_argv[0] = "CREATE TABLE sqlite_master (\n" | |
2890 " type text,\n" | |
2891 " name text,\n" | |
2892 " tbl_name text,\n" | |
2893 " rootpage integer,\n" | |
2894 " sql text\n" | |
2895 ")"; | |
2896 new_argv[1] = 0; | |
2897 new_colv[0] = "sql"; | |
2898 new_colv[1] = 0; | |
2899 callback(&data, 1, new_argv, new_colv); | |
2900 rc = SQLITE_OK; | |
2901 }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ | |
2902 char *new_argv[2], *new_colv[2]; | |
2903 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" | |
2904 " type text,\n" | |
2905 " name text,\n" | |
2906 " tbl_name text,\n" | |
2907 " rootpage integer,\n" | |
2908 " sql text\n" | |
2909 ")"; | |
2910 new_argv[1] = 0; | |
2911 new_colv[0] = "sql"; | |
2912 new_colv[1] = 0; | |
2913 callback(&data, 1, new_argv, new_colv); | |
2914 rc = SQLITE_OK; | |
2915 }else{ | |
2916 zShellStatic = azArg[1]; | |
2917 rc = sqlite3_exec(p->db, | |
2918 "SELECT sql FROM " | |
2919 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | |
2920 " FROM sqlite_master UNION ALL" | |
2921 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | |
2922 "WHERE lower(tbl_name) LIKE shellstatic()" | |
2923 " AND type!='meta' AND sql NOTNULL " | |
2924 "ORDER BY rowid", | |
2925 callback, &data, &zErrMsg); | |
2926 zShellStatic = 0; | |
2927 } | |
2928 }else if( nArg==1 ){ | |
2929 rc = sqlite3_exec(p->db, | |
2930 "SELECT sql FROM " | |
2931 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | |
2932 " FROM sqlite_master UNION ALL" | |
2933 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | |
2934 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" | |
2935 "ORDER BY rowid", | |
2936 callback, &data, &zErrMsg | |
2937 ); | |
2938 }else{ | |
2939 fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); | |
2940 rc = 1; | |
2941 goto meta_command_exit; | |
2942 } | |
2943 if( zErrMsg ){ | |
2944 fprintf(stderr,"Error: %s\n", zErrMsg); | |
2945 sqlite3_free(zErrMsg); | |
2946 rc = 1; | |
2947 }else if( rc != SQLITE_OK ){ | |
2948 fprintf(stderr,"Error: querying schema information\n"); | |
2949 rc = 1; | |
2950 }else{ | |
2951 rc = 0; | |
2952 } | |
2953 }else | |
2954 | |
2955 #ifdef SQLITE_DEBUG | |
2956 /* Undocumented commands for internal testing. Subject to change | |
2957 ** without notice. */ | |
2958 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ | |
2959 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ | |
2960 int i, v; | |
2961 for(i=1; i<nArg; i++){ | |
2962 v = booleanValue(azArg[i]); | |
2963 fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); | |
2964 } | |
2965 } | |
2966 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ | |
2967 int i; sqlite3_int64 v; | |
2968 for(i=1; i<nArg; i++){ | |
2969 char zBuf[200]; | |
2970 v = integerValue(azArg[i]); | |
2971 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v); | |
2972 fprintf(p->out, "%s", zBuf); | |
2973 } | |
2974 } | |
2975 }else | |
2976 #endif | |
2977 | |
2978 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ | |
2979 if( nArg==2 ){ | |
2980 sqlite3_snprintf(sizeof(p->separator), p->separator, | |
2981 "%.*s", (int)sizeof(p->separator)-1, azArg[1]); | |
2982 }else{ | |
2983 fprintf(stderr, "Usage: .separator STRING\n"); | |
2984 rc = 1; | |
2985 } | |
2986 }else | |
2987 | |
2988 if( c=='s' | |
2989 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) | |
2990 ){ | |
2991 char *zCmd; | |
2992 int i; | |
2993 if( nArg<2 ){ | |
2994 fprintf(stderr, "Usage: .system COMMAND\n"); | |
2995 rc = 1; | |
2996 goto meta_command_exit; | |
2997 } | |
2998 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); | |
2999 for(i=2; i<nArg; i++){ | |
3000 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"", | |
3001 zCmd, azArg[i]); | |
3002 } | |
3003 (void)system(zCmd); | |
3004 sqlite3_free(zCmd); | |
3005 }else | |
3006 | |
3007 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ | |
3008 int i; | |
3009 if( nArg!=1 ){ | |
3010 fprintf(stderr, "Usage: .show\n"); | |
3011 rc = 1; | |
3012 goto meta_command_exit; | |
3013 } | |
3014 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); | |
3015 fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); | |
3016 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); | |
3017 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); | |
3018 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); | |
3019 fprintf(p->out,"%9.9s: ", "nullvalue"); | |
3020 output_c_string(p->out, p->nullvalue); | |
3021 fprintf(p->out, "\n"); | |
3022 fprintf(p->out,"%9.9s: %s\n","output", | |
3023 strlen30(p->outfile) ? p->outfile : "stdout"); | |
3024 fprintf(p->out,"%9.9s: ", "separator"); | |
3025 output_c_string(p->out, p->separator); | |
3026 fprintf(p->out, "\n"); | |
3027 fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off"); | |
3028 fprintf(p->out,"%9.9s: ","width"); | |
3029 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { | |
3030 fprintf(p->out,"%d ",p->colWidth[i]); | |
3031 } | |
3032 fprintf(p->out,"\n"); | |
3033 }else | |
3034 | |
3035 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ | |
3036 if( nArg==2 ){ | |
3037 p->statsOn = booleanValue(azArg[1]); | |
3038 }else{ | |
3039 fprintf(stderr, "Usage: .stats on|off\n"); | |
3040 rc = 1; | |
3041 } | |
3042 }else | |
3043 | |
3044 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ | |
3045 sqlite3_stmt *pStmt; | |
3046 char **azResult; | |
3047 int nRow, nAlloc; | |
3048 char *zSql = 0; | |
3049 int ii; | |
3050 open_db(p, 0); | |
3051 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); | |
3052 if( rc ) return rc; | |
3053 zSql = sqlite3_mprintf( | |
3054 "SELECT name FROM sqlite_master" | |
3055 " WHERE type IN ('table','view')" | |
3056 " AND name NOT LIKE 'sqlite_%%'" | |
3057 " AND name LIKE ?1"); | |
3058 while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
3059 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); | |
3060 if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; | |
3061 if( strcmp(zDbName,"temp")==0 ){ | |
3062 zSql = sqlite3_mprintf( | |
3063 "%z UNION ALL " | |
3064 "SELECT 'temp.' || name FROM sqlite_temp_master" | |
3065 " WHERE type IN ('table','view')" | |
3066 " AND name NOT LIKE 'sqlite_%%'" | |
3067 " AND name LIKE ?1", zSql); | |
3068 }else{ | |
3069 zSql = sqlite3_mprintf( | |
3070 "%z UNION ALL " | |
3071 "SELECT '%q.' || name FROM \"%w\".sqlite_master" | |
3072 " WHERE type IN ('table','view')" | |
3073 " AND name NOT LIKE 'sqlite_%%'" | |
3074 " AND name LIKE ?1", zSql, zDbName, zDbName); | |
3075 } | |
3076 } | |
3077 sqlite3_finalize(pStmt); | |
3078 zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); | |
3079 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | |
3080 sqlite3_free(zSql); | |
3081 if( rc ) return rc; | |
3082 nRow = nAlloc = 0; | |
3083 azResult = 0; | |
3084 if( nArg>1 ){ | |
3085 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); | |
3086 }else{ | |
3087 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); | |
3088 } | |
3089 while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
3090 if( nRow>=nAlloc ){ | |
3091 char **azNew; | |
3092 int n = nAlloc*2 + 10; | |
3093 azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n); | |
3094 if( azNew==0 ){ | |
3095 fprintf(stderr, "Error: out of memory\n"); | |
3096 break; | |
3097 } | |
3098 nAlloc = n; | |
3099 azResult = azNew; | |
3100 } | |
3101 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); | |
3102 if( azResult[nRow] ) nRow++; | |
3103 } | |
3104 sqlite3_finalize(pStmt); | |
3105 if( nRow>0 ){ | |
3106 int len, maxlen = 0; | |
3107 int i, j; | |
3108 int nPrintCol, nPrintRow; | |
3109 for(i=0; i<nRow; i++){ | |
3110 len = strlen30(azResult[i]); | |
3111 if( len>maxlen ) maxlen = len; | |
3112 } | |
3113 nPrintCol = 80/(maxlen+2); | |
3114 if( nPrintCol<1 ) nPrintCol = 1; | |
3115 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; | |
3116 for(i=0; i<nPrintRow; i++){ | |
3117 for(j=i; j<nRow; j+=nPrintRow){ | |
3118 char *zSp = j<nPrintRow ? "" : " "; | |
3119 fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); | |
3120 } | |
3121 fprintf(p->out, "\n"); | |
3122 } | |
3123 } | |
3124 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); | |
3125 sqlite3_free(azResult); | |
3126 }else | |
3127 | |
3128 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ | |
3129 static const struct { | |
3130 const char *zCtrlName; /* Name of a test-control option */ | |
3131 int ctrlCode; /* Integer code for that option */ | |
3132 } aCtrl[] = { | |
3133 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, | |
3134 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, | |
3135 { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, | |
3136 { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, | |
3137 { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, | |
3138 { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS }, | |
3139 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE }, | |
3140 { "assert", SQLITE_TESTCTRL_ASSERT }, | |
3141 { "always", SQLITE_TESTCTRL_ALWAYS }, | |
3142 { "reserve", SQLITE_TESTCTRL_RESERVE }, | |
3143 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, | |
3144 { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, | |
3145 { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, | |
3146 { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, | |
3147 }; | |
3148 int testctrl = -1; | |
3149 int rc = 0; | |
3150 int i, n; | |
3151 open_db(p, 0); | |
3152 | |
3153 /* convert testctrl text option to value. allow any unique prefix | |
3154 ** of the option name, or a numerical value. */ | |
3155 n = strlen30(azArg[1]); | |
3156 for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){ | |
3157 if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){ | |
3158 if( testctrl<0 ){ | |
3159 testctrl = aCtrl[i].ctrlCode; | |
3160 }else{ | |
3161 fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]); | |
3162 testctrl = -1; | |
3163 break; | |
3164 } | |
3165 } | |
3166 } | |
3167 if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); | |
3168 if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){ | |
3169 fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); | |
3170 }else{ | |
3171 switch(testctrl){ | |
3172 | |
3173 /* sqlite3_test_control(int, db, int) */ | |
3174 case SQLITE_TESTCTRL_OPTIMIZATIONS: | |
3175 case SQLITE_TESTCTRL_RESERVE: | |
3176 if( nArg==3 ){ | |
3177 int opt = (int)strtol(azArg[2], 0, 0); | |
3178 rc = sqlite3_test_control(testctrl, p->db, opt); | |
3179 fprintf(p->out, "%d (0x%08x)\n", rc, rc); | |
3180 } else { | |
3181 fprintf(stderr,"Error: testctrl %s takes a single int option\n", | |
3182 azArg[1]); | |
3183 } | |
3184 break; | |
3185 | |
3186 /* sqlite3_test_control(int) */ | |
3187 case SQLITE_TESTCTRL_PRNG_SAVE: | |
3188 case SQLITE_TESTCTRL_PRNG_RESTORE: | |
3189 case SQLITE_TESTCTRL_PRNG_RESET: | |
3190 case SQLITE_TESTCTRL_BYTEORDER: | |
3191 if( nArg==2 ){ | |
3192 rc = sqlite3_test_control(testctrl); | |
3193 fprintf(p->out, "%d (0x%08x)\n", rc, rc); | |
3194 } else { | |
3195 fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]); | |
3196 } | |
3197 break; | |
3198 | |
3199 /* sqlite3_test_control(int, uint) */ | |
3200 case SQLITE_TESTCTRL_PENDING_BYTE: | |
3201 if( nArg==3 ){ | |
3202 unsigned int opt = (unsigned int)integerValue(azArg[2]); | |
3203 rc = sqlite3_test_control(testctrl, opt); | |
3204 fprintf(p->out, "%d (0x%08x)\n", rc, rc); | |
3205 } else { | |
3206 fprintf(stderr,"Error: testctrl %s takes a single unsigned" | |
3207 " int option\n", azArg[1]); | |
3208 } | |
3209 break; | |
3210 | |
3211 /* sqlite3_test_control(int, int) */ | |
3212 case SQLITE_TESTCTRL_ASSERT: | |
3213 case SQLITE_TESTCTRL_ALWAYS: | |
3214 if( nArg==3 ){ | |
3215 int opt = booleanValue(azArg[2]); | |
3216 rc = sqlite3_test_control(testctrl, opt); | |
3217 fprintf(p->out, "%d (0x%08x)\n", rc, rc); | |
3218 } else { | |
3219 fprintf(stderr,"Error: testctrl %s takes a single int option\n", | |
3220 azArg[1]); | |
3221 } | |
3222 break; | |
3223 | |
3224 /* sqlite3_test_control(int, char *) */ | |
3225 #ifdef SQLITE_N_KEYWORD | |
3226 case SQLITE_TESTCTRL_ISKEYWORD: | |
3227 if( nArg==3 ){ | |
3228 const char *opt = azArg[2]; | |
3229 rc = sqlite3_test_control(testctrl, opt); | |
3230 fprintf(p->out, "%d (0x%08x)\n", rc, rc); | |
3231 } else { | |
3232 fprintf(stderr,"Error: testctrl %s takes a single char * option\n", | |
3233 azArg[1]); | |
3234 } | |
3235 break; | |
3236 #endif | |
3237 | |
3238 case SQLITE_TESTCTRL_BITVEC_TEST: | |
3239 case SQLITE_TESTCTRL_FAULT_INSTALL: | |
3240 case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: | |
3241 case SQLITE_TESTCTRL_SCRATCHMALLOC: | |
3242 default: | |
3243 fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n", | |
3244 azArg[1]); | |
3245 break; | |
3246 } | |
3247 } | |
3248 }else | |
3249 | |
3250 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ | |
3251 open_db(p, 0); | |
3252 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); | |
3253 }else | |
3254 | |
3255 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ | |
3256 if( nArg==2 ){ | |
3257 enableTimer = booleanValue(azArg[1]); | |
3258 if( enableTimer && !HAS_TIMER ){ | |
3259 fprintf(stderr, "Error: timer not available on this system.\n"); | |
3260 enableTimer = 0; | |
3261 } | |
3262 }else{ | |
3263 fprintf(stderr, "Usage: .timer on|off\n"); | |
3264 rc = 1; | |
3265 } | |
3266 }else | |
3267 | |
3268 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ | |
3269 open_db(p, 0); | |
3270 output_file_close(p->traceOut); | |
3271 if( nArg!=2 ){ | |
3272 fprintf(stderr, "Usage: .trace FILE|off\n"); | |
3273 rc = 1; | |
3274 goto meta_command_exit; | |
3275 } | |
3276 p->traceOut = output_file_open(azArg[1]); | |
3277 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) | |
3278 if( p->traceOut==0 ){ | |
3279 sqlite3_trace(p->db, 0, 0); | |
3280 }else{ | |
3281 sqlite3_trace(p->db, sql_trace_callback, p->traceOut); | |
3282 } | |
3283 #endif | |
3284 }else | |
3285 | |
3286 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ | |
3287 fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/, | |
3288 sqlite3_libversion(), sqlite3_sourceid()); | |
3289 }else | |
3290 | |
3291 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ | |
3292 const char *zDbName = nArg==2 ? azArg[1] : "main"; | |
3293 char *zVfsName = 0; | |
3294 if( p->db ){ | |
3295 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); | |
3296 if( zVfsName ){ | |
3297 fprintf(p->out, "%s\n", zVfsName); | |
3298 sqlite3_free(zVfsName); | |
3299 } | |
3300 } | |
3301 }else | |
3302 | |
3303 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) | |
3304 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ | |
3305 extern int sqlite3WhereTrace; | |
3306 sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; | |
3307 }else | |
3308 #endif | |
3309 | |
3310 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ | |
3311 int j; | |
3312 assert( nArg<=ArraySize(azArg) ); | |
3313 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ | |
3314 p->colWidth[j-1] = (int)integerValue(azArg[j]); | |
3315 } | |
3316 }else | |
3317 | |
3318 { | |
3319 fprintf(stderr, "Error: unknown command or invalid arguments: " | |
3320 " \"%s\". Enter \".help\" for help\n", azArg[0]); | |
3321 rc = 1; | |
3322 } | |
3323 | |
3324 meta_command_exit: | |
3325 if( p->outCount ){ | |
3326 p->outCount--; | |
3327 if( p->outCount==0 ) output_reset(p); | |
3328 } | |
3329 return rc; | |
3330 } | |
3331 | |
3332 /* | |
3333 ** Return TRUE if a semicolon occurs anywhere in the first N characters | |
3334 ** of string z[]. | |
3335 */ | |
3336 static int line_contains_semicolon(const char *z, int N){ | |
3337 int i; | |
3338 for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } | |
3339 return 0; | |
3340 } | |
3341 | |
3342 /* | |
3343 ** Test to see if a line consists entirely of whitespace. | |
3344 */ | |
3345 static int _all_whitespace(const char *z){ | |
3346 for(; *z; z++){ | |
3347 if( IsSpace(z[0]) ) continue; | |
3348 if( *z=='/' && z[1]=='*' ){ | |
3349 z += 2; | |
3350 while( *z && (*z!='*' || z[1]!='/') ){ z++; } | |
3351 if( *z==0 ) return 0; | |
3352 z++; | |
3353 continue; | |
3354 } | |
3355 if( *z=='-' && z[1]=='-' ){ | |
3356 z += 2; | |
3357 while( *z && *z!='\n' ){ z++; } | |
3358 if( *z==0 ) return 1; | |
3359 continue; | |
3360 } | |
3361 return 0; | |
3362 } | |
3363 return 1; | |
3364 } | |
3365 | |
3366 /* | |
3367 ** Return TRUE if the line typed in is an SQL command terminator other | |
3368 ** than a semi-colon. The SQL Server style "go" command is understood | |
3369 ** as is the Oracle "/". | |
3370 */ | |
3371 static int line_is_command_terminator(const char *zLine){ | |
3372 while( IsSpace(zLine[0]) ){ zLine++; }; | |
3373 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){ | |
3374 return 1; /* Oracle */ | |
3375 } | |
3376 if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' | |
3377 && _all_whitespace(&zLine[2]) ){ | |
3378 return 1; /* SQL Server */ | |
3379 } | |
3380 return 0; | |
3381 } | |
3382 | |
3383 /* | |
3384 ** Return true if zSql is a complete SQL statement. Return false if it | |
3385 ** ends in the middle of a string literal or C-style comment. | |
3386 */ | |
3387 static int line_is_complete(char *zSql, int nSql){ | |
3388 int rc; | |
3389 if( zSql==0 ) return 1; | |
3390 zSql[nSql] = ';'; | |
3391 zSql[nSql+1] = 0; | |
3392 rc = sqlite3_complete(zSql); | |
3393 zSql[nSql] = 0; | |
3394 return rc; | |
3395 } | |
3396 | |
3397 /* | |
3398 ** Read input from *in and process it. If *in==0 then input | |
3399 ** is interactive - the user is typing it it. Otherwise, input | |
3400 ** is coming from a file or device. A prompt is issued and history | |
3401 ** is saved only if input is interactive. An interrupt signal will | |
3402 ** cause this routine to exit immediately, unless input is interactive. | |
3403 ** | |
3404 ** Return the number of errors. | |
3405 */ | |
3406 static int process_input(struct callback_data *p, FILE *in){ | |
3407 char *zLine = 0; /* A single input line */ | |
3408 char *zSql = 0; /* Accumulated SQL text */ | |
3409 int nLine; /* Length of current line */ | |
3410 int nSql = 0; /* Bytes of zSql[] used */ | |
3411 int nAlloc = 0; /* Allocated zSql[] space */ | |
3412 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ | |
3413 char *zErrMsg; /* Error message returned */ | |
3414 int rc; /* Error code */ | |
3415 int errCnt = 0; /* Number of errors seen */ | |
3416 int lineno = 0; /* Current line number */ | |
3417 int startline = 0; /* Line number for start of current input */ | |
3418 | |
3419 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ | |
3420 fflush(p->out); | |
3421 zLine = one_input_line(in, zLine, nSql>0); | |
3422 if( zLine==0 ){ | |
3423 /* End of input */ | |
3424 if( stdin_is_interactive ) printf("\n"); | |
3425 break; | |
3426 } | |
3427 if( seenInterrupt ){ | |
3428 if( in!=0 ) break; | |
3429 seenInterrupt = 0; | |
3430 } | |
3431 lineno++; | |
3432 if( nSql==0 && _all_whitespace(zLine) ){ | |
3433 if( p->echoOn ) printf("%s\n", zLine); | |
3434 continue; | |
3435 } | |
3436 if( zLine && zLine[0]=='.' && nSql==0 ){ | |
3437 if( p->echoOn ) printf("%s\n", zLine); | |
3438 rc = do_meta_command(zLine, p); | |
3439 if( rc==2 ){ /* exit requested */ | |
3440 break; | |
3441 }else if( rc ){ | |
3442 errCnt++; | |
3443 } | |
3444 continue; | |
3445 } | |
3446 if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ | |
3447 memcpy(zLine,";",2); | |
3448 } | |
3449 nLine = strlen30(zLine); | |
3450 if( nSql+nLine+2>=nAlloc ){ | |
3451 nAlloc = nSql+nLine+100; | |
3452 zSql = realloc(zSql, nAlloc); | |
3453 if( zSql==0 ){ | |
3454 fprintf(stderr, "Error: out of memory\n"); | |
3455 exit(1); | |
3456 } | |
3457 } | |
3458 nSqlPrior = nSql; | |
3459 if( nSql==0 ){ | |
3460 int i; | |
3461 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} | |
3462 assert( nAlloc>0 && zSql!=0 ); | |
3463 memcpy(zSql, zLine+i, nLine+1-i); | |
3464 startline = lineno; | |
3465 nSql = nLine-i; | |
3466 }else{ | |
3467 zSql[nSql++] = '\n'; | |
3468 memcpy(zSql+nSql, zLine, nLine+1); | |
3469 nSql += nLine; | |
3470 } | |
3471 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) | |
3472 && sqlite3_complete(zSql) ){ | |
3473 p->cnt = 0; | |
3474 open_db(p, 0); | |
3475 BEGIN_TIMER; | |
3476 rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); | |
3477 END_TIMER; | |
3478 if( rc || zErrMsg ){ | |
3479 char zPrefix[100]; | |
3480 if( in!=0 || !stdin_is_interactive ){ | |
3481 sqlite3_snprintf(sizeof(zPrefix), zPrefix, | |
3482 "Error: near line %d:", startline); | |
3483 }else{ | |
3484 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); | |
3485 } | |
3486 if( zErrMsg!=0 ){ | |
3487 fprintf(stderr, "%s %s\n", zPrefix, zErrMsg); | |
3488 sqlite3_free(zErrMsg); | |
3489 zErrMsg = 0; | |
3490 }else{ | |
3491 fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); | |
3492 } | |
3493 errCnt++; | |
3494 } | |
3495 nSql = 0; | |
3496 if( p->outCount ){ | |
3497 output_reset(p); | |
3498 p->outCount = 0; | |
3499 } | |
3500 }else if( nSql && _all_whitespace(zSql) ){ | |
3501 if( p->echoOn ) printf("%s\n", zSql); | |
3502 nSql = 0; | |
3503 } | |
3504 } | |
3505 if( nSql ){ | |
3506 if( !_all_whitespace(zSql) ){ | |
3507 fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); | |
3508 } | |
3509 free(zSql); | |
3510 } | |
3511 free(zLine); | |
3512 return errCnt>0; | |
3513 } | |
3514 | |
3515 /* | |
3516 ** Return a pathname which is the user's home directory. A | |
3517 ** 0 return indicates an error of some kind. | |
3518 */ | |
3519 static char *find_home_dir(void){ | |
3520 static char *home_dir = NULL; | |
3521 if( home_dir ) return home_dir; | |
3522 | |
3523 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) | |
3524 { | |
3525 struct passwd *pwent; | |
3526 uid_t uid = getuid(); | |
3527 if( (pwent=getpwuid(uid)) != NULL) { | |
3528 home_dir = pwent->pw_dir; | |
3529 } | |
3530 } | |
3531 #endif | |
3532 | |
3533 #if defined(_WIN32_WCE) | |
3534 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() | |
3535 */ | |
3536 home_dir = "/"; | |
3537 #else | |
3538 | |
3539 #if defined(_WIN32) || defined(WIN32) | |
3540 if (!home_dir) { | |
3541 home_dir = getenv("USERPROFILE"); | |
3542 } | |
3543 #endif | |
3544 | |
3545 if (!home_dir) { | |
3546 home_dir = getenv("HOME"); | |
3547 } | |
3548 | |
3549 #if defined(_WIN32) || defined(WIN32) | |
3550 if (!home_dir) { | |
3551 char *zDrive, *zPath; | |
3552 int n; | |
3553 zDrive = getenv("HOMEDRIVE"); | |
3554 zPath = getenv("HOMEPATH"); | |
3555 if( zDrive && zPath ){ | |
3556 n = strlen30(zDrive) + strlen30(zPath) + 1; | |
3557 home_dir = malloc( n ); | |
3558 if( home_dir==0 ) return 0; | |
3559 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); | |
3560 return home_dir; | |
3561 } | |
3562 home_dir = "c:\\"; | |
3563 } | |
3564 #endif | |
3565 | |
3566 #endif /* !_WIN32_WCE */ | |
3567 | |
3568 if( home_dir ){ | |
3569 int n = strlen30(home_dir) + 1; | |
3570 char *z = malloc( n ); | |
3571 if( z ) memcpy(z, home_dir, n); | |
3572 home_dir = z; | |
3573 } | |
3574 | |
3575 return home_dir; | |
3576 } | |
3577 | |
3578 /* | |
3579 ** Read input from the file given by sqliterc_override. Or if that | |
3580 ** parameter is NULL, take input from ~/.sqliterc | |
3581 ** | |
3582 ** Returns the number of errors. | |
3583 */ | |
3584 static int process_sqliterc( | |
3585 struct callback_data *p, /* Configuration data */ | |
3586 const char *sqliterc_override /* Name of config file. NULL to use default */ | |
3587 ){ | |
3588 char *home_dir = NULL; | |
3589 const char *sqliterc = sqliterc_override; | |
3590 char *zBuf = 0; | |
3591 FILE *in = NULL; | |
3592 int rc = 0; | |
3593 | |
3594 if (sqliterc == NULL) { | |
3595 home_dir = find_home_dir(); | |
3596 if( home_dir==0 ){ | |
3597 #if !defined(__RTP__) && !defined(_WRS_KERNEL) | |
3598 fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); | |
3599 #endif | |
3600 return 1; | |
3601 } | |
3602 sqlite3_initialize(); | |
3603 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); | |
3604 sqliterc = zBuf; | |
3605 } | |
3606 in = fopen(sqliterc,"rb"); | |
3607 if( in ){ | |
3608 if( stdin_is_interactive ){ | |
3609 fprintf(stderr,"-- Loading resources from %s\n",sqliterc); | |
3610 } | |
3611 rc = process_input(p,in); | |
3612 fclose(in); | |
3613 } | |
3614 sqlite3_free(zBuf); | |
3615 return rc; | |
3616 } | |
3617 | |
3618 /* | |
3619 ** Show available command line options | |
3620 */ | |
3621 static const char zOptions[] = | |
3622 " -bail stop after hitting an error\n" | |
3623 " -batch force batch I/O\n" | |
3624 " -column set output mode to 'column'\n" | |
3625 " -cmd COMMAND run \"COMMAND\" before reading stdin\n" | |
3626 " -csv set output mode to 'csv'\n" | |
3627 " -echo print commands before execution\n" | |
3628 " -init FILENAME read/process named file\n" | |
3629 " -[no]header turn headers on or off\n" | |
3630 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) | |
3631 " -heap SIZE Size of heap for memsys3 or memsys5\n" | |
3632 #endif | |
3633 " -help show this message\n" | |
3634 " -html set output mode to HTML\n" | |
3635 " -interactive force interactive I/O\n" | |
3636 " -line set output mode to 'line'\n" | |
3637 " -list set output mode to 'list'\n" | |
3638 " -mmap N default mmap size set to N\n" | |
3639 #ifdef SQLITE_ENABLE_MULTIPLEX | |
3640 " -multiplex enable the multiplexor VFS\n" | |
3641 #endif | |
3642 " -nullvalue TEXT set text string for NULL values. Default ''\n" | |
3643 " -separator SEP set output field separator. Default: '|'\n" | |
3644 " -stats print memory stats before each finalize\n" | |
3645 " -version show SQLite version\n" | |
3646 " -vfs NAME use NAME as the default VFS\n" | |
3647 #ifdef SQLITE_ENABLE_VFSTRACE | |
3648 " -vfstrace enable tracing of all VFS calls\n" | |
3649 #endif | |
3650 ; | |
3651 static void usage(int showDetail){ | |
3652 fprintf(stderr, | |
3653 "Usage: %s [OPTIONS] FILENAME [SQL]\n" | |
3654 "FILENAME is the name of an SQLite database. A new database is created\n" | |
3655 "if the file does not previously exist.\n", Argv0); | |
3656 if( showDetail ){ | |
3657 fprintf(stderr, "OPTIONS include:\n%s", zOptions); | |
3658 }else{ | |
3659 fprintf(stderr, "Use the -help option for additional information\n"); | |
3660 } | |
3661 exit(1); | |
3662 } | |
3663 | |
3664 /* | |
3665 ** Initialize the state information in data | |
3666 */ | |
3667 static void main_init(struct callback_data *data) { | |
3668 memset(data, 0, sizeof(*data)); | |
3669 data->mode = MODE_List; | |
3670 memcpy(data->separator,"|", 2); | |
3671 data->showHeader = 0; | |
3672 sqlite3_config(SQLITE_CONFIG_URI, 1); | |
3673 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); | |
3674 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); | |
3675 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); | |
3676 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); | |
3677 } | |
3678 | |
3679 /* | |
3680 ** Output text to the console in a font that attracts extra attention. | |
3681 */ | |
3682 #ifdef _WIN32 | |
3683 static void printBold(const char *zText){ | |
3684 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); | |
3685 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; | |
3686 GetConsoleScreenBufferInfo(out, &defaultScreenInfo); | |
3687 SetConsoleTextAttribute(out, | |
3688 FOREGROUND_RED|FOREGROUND_INTENSITY | |
3689 ); | |
3690 printf("%s", zText); | |
3691 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); | |
3692 } | |
3693 #else | |
3694 static void printBold(const char *zText){ | |
3695 printf("\033[1m%s\033[0m", zText); | |
3696 } | |
3697 #endif | |
3698 | |
3699 /* | |
3700 ** Get the argument to an --option. Throw an error and die if no argument | |
3701 ** is available. | |
3702 */ | |
3703 static char *cmdline_option_value(int argc, char **argv, int i){ | |
3704 if( i==argc ){ | |
3705 fprintf(stderr, "%s: Error: missing argument to %s\n", | |
3706 argv[0], argv[argc-1]); | |
3707 exit(1); | |
3708 } | |
3709 return argv[i]; | |
3710 } | |
3711 | |
3712 int main(int argc, char **argv){ | |
3713 char *zErrMsg = 0; | |
3714 struct callback_data data; | |
3715 const char *zInitFile = 0; | |
3716 char *zFirstCmd = 0; | |
3717 int i; | |
3718 int rc = 0; | |
3719 int warnInmemoryDb = 0; | |
3720 | |
3721 #if USE_SYSTEM_SQLITE+0!=1 | |
3722 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ | |
3723 fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", | |
3724 sqlite3_sourceid(), SQLITE_SOURCE_ID); | |
3725 exit(1); | |
3726 } | |
3727 #endif | |
3728 Argv0 = argv[0]; | |
3729 main_init(&data); | |
3730 stdin_is_interactive = isatty(0); | |
3731 | |
3732 /* Make sure we have a valid signal handler early, before anything | |
3733 ** else is done. | |
3734 */ | |
3735 #ifdef SIGINT | |
3736 signal(SIGINT, interrupt_handler); | |
3737 #endif | |
3738 | |
3739 /* Do an initial pass through the command-line argument to locate | |
3740 ** the name of the database file, the name of the initialization file, | |
3741 ** the size of the alternative malloc heap, | |
3742 ** and the first command to execute. | |
3743 */ | |
3744 for(i=1; i<argc; i++){ | |
3745 char *z; | |
3746 z = argv[i]; | |
3747 if( z[0]!='-' ){ | |
3748 if( data.zDbFilename==0 ){ | |
3749 data.zDbFilename = z; | |
3750 continue; | |
3751 } | |
3752 if( zFirstCmd==0 ){ | |
3753 zFirstCmd = z; | |
3754 continue; | |
3755 } | |
3756 fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]); | |
3757 fprintf(stderr,"Use -help for a list of options.\n"); | |
3758 return 1; | |
3759 } | |
3760 if( z[1]=='-' ) z++; | |
3761 if( strcmp(z,"-separator")==0 | |
3762 || strcmp(z,"-nullvalue")==0 | |
3763 || strcmp(z,"-cmd")==0 | |
3764 ){ | |
3765 (void)cmdline_option_value(argc, argv, ++i); | |
3766 }else if( strcmp(z,"-init")==0 ){ | |
3767 zInitFile = cmdline_option_value(argc, argv, ++i); | |
3768 }else if( strcmp(z,"-batch")==0 ){ | |
3769 /* Need to check for batch mode here to so we can avoid printing | |
3770 ** informational messages (like from process_sqliterc) before | |
3771 ** we do the actual processing of arguments later in a second pass. | |
3772 */ | |
3773 stdin_is_interactive = 0; | |
3774 }else if( strcmp(z,"-heap")==0 ){ | |
3775 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) | |
3776 const char *zSize; | |
3777 sqlite3_int64 szHeap; | |
3778 | |
3779 zSize = cmdline_option_value(argc, argv, ++i); | |
3780 szHeap = integerValue(zSize); | |
3781 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; | |
3782 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); | |
3783 #endif | |
3784 #ifdef SQLITE_ENABLE_VFSTRACE | |
3785 }else if( strcmp(z,"-vfstrace")==0 ){ | |
3786 extern int vfstrace_register( | |
3787 const char *zTraceName, | |
3788 const char *zOldVfsName, | |
3789 int (*xOut)(const char*,void*), | |
3790 void *pOutArg, | |
3791 int makeDefault | |
3792 ); | |
3793 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); | |
3794 #endif | |
3795 #ifdef SQLITE_ENABLE_MULTIPLEX | |
3796 }else if( strcmp(z,"-multiplex")==0 ){ | |
3797 extern int sqlite3_multiple_initialize(const char*,int); | |
3798 sqlite3_multiplex_initialize(0, 1); | |
3799 #endif | |
3800 }else if( strcmp(z,"-mmap")==0 ){ | |
3801 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); | |
3802 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); | |
3803 }else if( strcmp(z,"-vfs")==0 ){ | |
3804 sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i)); | |
3805 if( pVfs ){ | |
3806 sqlite3_vfs_register(pVfs, 1); | |
3807 }else{ | |
3808 fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); | |
3809 exit(1); | |
3810 } | |
3811 } | |
3812 } | |
3813 if( data.zDbFilename==0 ){ | |
3814 #ifndef SQLITE_OMIT_MEMORYDB | |
3815 data.zDbFilename = ":memory:"; | |
3816 warnInmemoryDb = argc==1; | |
3817 #else | |
3818 fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); | |
3819 return 1; | |
3820 #endif | |
3821 #ifdef SQLITE_SHELL_DBNAME_PROC | |
3822 { extern void SQLITE_SHELL_DBNAME_PROC(const char**); | |
3823 SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename); | |
3824 warnInmemoryDb = 0; } | |
3825 #endif | |
3826 } | |
3827 data.out = stdout; | |
3828 | |
3829 /* Go ahead and open the database file if it already exists. If the | |
3830 ** file does not exist, delay opening it. This prevents empty database | |
3831 ** files from being created if a user mistypes the database name argument | |
3832 ** to the sqlite command-line tool. | |
3833 */ | |
3834 if( access(data.zDbFilename, 0)==0 ){ | |
3835 open_db(&data, 0); | |
3836 } | |
3837 | |
3838 /* Process the initialization file if there is one. If no -init option | |
3839 ** is given on the command line, look for a file named ~/.sqliterc and | |
3840 ** try to process it. | |
3841 */ | |
3842 rc = process_sqliterc(&data,zInitFile); | |
3843 if( rc>0 ){ | |
3844 return rc; | |
3845 } | |
3846 | |
3847 /* Make a second pass through the command-line argument and set | |
3848 ** options. This second pass is delayed until after the initialization | |
3849 ** file is processed so that the command-line arguments will override | |
3850 ** settings in the initialization file. | |
3851 */ | |
3852 for(i=1; i<argc; i++){ | |
3853 char *z = argv[i]; | |
3854 if( z[0]!='-' ) continue; | |
3855 if( z[1]=='-' ){ z++; } | |
3856 if( strcmp(z,"-init")==0 ){ | |
3857 i++; | |
3858 }else if( strcmp(z,"-html")==0 ){ | |
3859 data.mode = MODE_Html; | |
3860 }else if( strcmp(z,"-list")==0 ){ | |
3861 data.mode = MODE_List; | |
3862 }else if( strcmp(z,"-line")==0 ){ | |
3863 data.mode = MODE_Line; | |
3864 }else if( strcmp(z,"-column")==0 ){ | |
3865 data.mode = MODE_Column; | |
3866 }else if( strcmp(z,"-csv")==0 ){ | |
3867 data.mode = MODE_Csv; | |
3868 memcpy(data.separator,",",2); | |
3869 }else if( strcmp(z,"-separator")==0 ){ | |
3870 sqlite3_snprintf(sizeof(data.separator), data.separator, | |
3871 "%s",cmdline_option_value(argc,argv,++i)); | |
3872 }else if( strcmp(z,"-nullvalue")==0 ){ | |
3873 sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, | |
3874 "%s",cmdline_option_value(argc,argv,++i)); | |
3875 }else if( strcmp(z,"-header")==0 ){ | |
3876 data.showHeader = 1; | |
3877 }else if( strcmp(z,"-noheader")==0 ){ | |
3878 data.showHeader = 0; | |
3879 }else if( strcmp(z,"-echo")==0 ){ | |
3880 data.echoOn = 1; | |
3881 }else if( strcmp(z,"-eqp")==0 ){ | |
3882 data.autoEQP = 1; | |
3883 }else if( strcmp(z,"-stats")==0 ){ | |
3884 data.statsOn = 1; | |
3885 }else if( strcmp(z,"-bail")==0 ){ | |
3886 bail_on_error = 1; | |
3887 }else if( strcmp(z,"-version")==0 ){ | |
3888 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); | |
3889 return 0; | |
3890 }else if( strcmp(z,"-interactive")==0 ){ | |
3891 stdin_is_interactive = 1; | |
3892 }else if( strcmp(z,"-batch")==0 ){ | |
3893 stdin_is_interactive = 0; | |
3894 }else if( strcmp(z,"-heap")==0 ){ | |
3895 i++; | |
3896 }else if( strcmp(z,"-mmap")==0 ){ | |
3897 i++; | |
3898 }else if( strcmp(z,"-vfs")==0 ){ | |
3899 i++; | |
3900 #ifdef SQLITE_ENABLE_VFSTRACE | |
3901 }else if( strcmp(z,"-vfstrace")==0 ){ | |
3902 i++; | |
3903 #endif | |
3904 #ifdef SQLITE_ENABLE_MULTIPLEX | |
3905 }else if( strcmp(z,"-multiplex")==0 ){ | |
3906 i++; | |
3907 #endif | |
3908 }else if( strcmp(z,"-help")==0 ){ | |
3909 usage(1); | |
3910 }else if( strcmp(z,"-cmd")==0 ){ | |
3911 if( i==argc-1 ) break; | |
3912 z = cmdline_option_value(argc,argv,++i); | |
3913 if( z[0]=='.' ){ | |
3914 rc = do_meta_command(z, &data); | |
3915 if( rc && bail_on_error ) return rc==2 ? 0 : rc; | |
3916 }else{ | |
3917 open_db(&data, 0); | |
3918 rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg); | |
3919 if( zErrMsg!=0 ){ | |
3920 fprintf(stderr,"Error: %s\n", zErrMsg); | |
3921 if( bail_on_error ) return rc!=0 ? rc : 1; | |
3922 }else if( rc!=0 ){ | |
3923 fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z); | |
3924 if( bail_on_error ) return rc; | |
3925 } | |
3926 } | |
3927 }else{ | |
3928 fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); | |
3929 fprintf(stderr,"Use -help for a list of options.\n"); | |
3930 return 1; | |
3931 } | |
3932 } | |
3933 | |
3934 if( zFirstCmd ){ | |
3935 /* Run just the command that follows the database name | |
3936 */ | |
3937 if( zFirstCmd[0]=='.' ){ | |
3938 rc = do_meta_command(zFirstCmd, &data); | |
3939 if( rc==2 ) rc = 0; | |
3940 }else{ | |
3941 open_db(&data, 0); | |
3942 rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg); | |
3943 if( zErrMsg!=0 ){ | |
3944 fprintf(stderr,"Error: %s\n", zErrMsg); | |
3945 return rc!=0 ? rc : 1; | |
3946 }else if( rc!=0 ){ | |
3947 fprintf(stderr,"Error: unable to process SQL \"%s\"\n", zFirstCmd); | |
3948 return rc; | |
3949 } | |
3950 } | |
3951 }else{ | |
3952 /* Run commands received from standard input | |
3953 */ | |
3954 if( stdin_is_interactive ){ | |
3955 char *zHome; | |
3956 char *zHistory = 0; | |
3957 int nHistory; | |
3958 printf( | |
3959 "SQLite version %s %.19s\n" /*extra-version-info*/ | |
3960 "Enter \".help\" for usage hints.\n", | |
3961 sqlite3_libversion(), sqlite3_sourceid() | |
3962 ); | |
3963 if( warnInmemoryDb ){ | |
3964 printf("Connected to a "); | |
3965 printBold("transient in-memory database"); | |
3966 printf(".\nUse \".open FILENAME\" to reopen on a " | |
3967 "persistent database.\n"); | |
3968 } | |
3969 zHome = find_home_dir(); | |
3970 if( zHome ){ | |
3971 nHistory = strlen30(zHome) + 20; | |
3972 if( (zHistory = malloc(nHistory))!=0 ){ | |
3973 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); | |
3974 } | |
3975 } | |
3976 #if defined(HAVE_READLINE) | |
3977 if( zHistory ) read_history(zHistory); | |
3978 #endif | |
3979 rc = process_input(&data, 0); | |
3980 if( zHistory ){ | |
3981 stifle_history(100); | |
3982 write_history(zHistory); | |
3983 free(zHistory); | |
3984 } | |
3985 }else{ | |
3986 rc = process_input(&data, stdin); | |
3987 } | |
3988 } | |
3989 set_table_name(&data, 0); | |
3990 if( data.db ){ | |
3991 sqlite3_close(data.db); | |
3992 } | |
3993 sqlite3_free(data.zFreeOnClose); | |
3994 return rc; | |
3995 } |