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