OLD | NEW |
1 /* | 1 /* |
2 ** 2001 September 15 | 2 ** 2001 September 15 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 83 |
84 # include "linenoise.h" | 84 # include "linenoise.h" |
85 # define shell_add_history(X) linenoiseHistoryAdd(X) | 85 # define shell_add_history(X) linenoiseHistoryAdd(X) |
86 # define shell_read_history(X) linenoiseHistoryLoad(X) | 86 # define shell_read_history(X) linenoiseHistoryLoad(X) |
87 # define shell_write_history(X) linenoiseHistorySave(X) | 87 # define shell_write_history(X) linenoiseHistorySave(X) |
88 # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) | 88 # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) |
89 # define shell_readline(X) linenoise(X) | 89 # define shell_readline(X) linenoise(X) |
90 | 90 |
91 #else | 91 #else |
92 | 92 |
93 # define shell_read_history(X) | 93 # define shell_read_history(X) |
94 # define shell_write_history(X) | 94 # define shell_write_history(X) |
95 # define shell_stifle_history(X) | 95 # define shell_stifle_history(X) |
96 | 96 |
97 # define SHELL_USE_LOCAL_GETLINE 1 | 97 # define SHELL_USE_LOCAL_GETLINE 1 |
98 #endif | 98 #endif |
99 | 99 |
100 | 100 |
101 #if defined(_WIN32) || defined(WIN32) | 101 #if defined(_WIN32) || defined(WIN32) |
102 # include <io.h> | 102 # include <io.h> |
103 # include <fcntl.h> | 103 # include <fcntl.h> |
(...skipping 25 matching lines...) Expand all Loading... |
129 * overridden with the -batch command line option. | 129 * overridden with the -batch command line option. |
130 */ | 130 */ |
131 #define isatty(x) 1 | 131 #define isatty(x) 1 |
132 #endif | 132 #endif |
133 | 133 |
134 /* ctype macros that work with signed characters */ | 134 /* ctype macros that work with signed characters */ |
135 #define IsSpace(X) isspace((unsigned char)X) | 135 #define IsSpace(X) isspace((unsigned char)X) |
136 #define IsDigit(X) isdigit((unsigned char)X) | 136 #define IsDigit(X) isdigit((unsigned char)X) |
137 #define ToLower(X) (char)tolower((unsigned char)X) | 137 #define ToLower(X) (char)tolower((unsigned char)X) |
138 | 138 |
| 139 #if defined(_WIN32) || defined(WIN32) |
| 140 #include <windows.h> |
| 141 |
| 142 /* string conversion routines only needed on Win32 */ |
| 143 extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); |
| 144 extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int); |
| 145 extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int); |
| 146 extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); |
| 147 #endif |
| 148 |
139 /* On Windows, we normally run with output mode of TEXT so that \n characters | 149 /* 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 | 150 ** are automatically translated into \r\n. However, this behavior needs |
141 ** to be disabled in some cases (ex: when generating CSV output and when | 151 ** to be disabled in some cases (ex: when generating CSV output and when |
142 ** rendering quoted strings that contain \n characters). The following | 152 ** rendering quoted strings that contain \n characters). The following |
143 ** routines take care of that. | 153 ** routines take care of that. |
144 */ | 154 */ |
145 #if defined(_WIN32) || defined(WIN32) | 155 #if defined(_WIN32) || defined(WIN32) |
146 static void setBinaryMode(FILE *out){ | 156 static void setBinaryMode(FILE *file, int isOutput){ |
147 fflush(out); | 157 if( isOutput ) fflush(file); |
148 _setmode(_fileno(out), _O_BINARY); | 158 _setmode(_fileno(file), _O_BINARY); |
149 } | 159 } |
150 static void setTextMode(FILE *out){ | 160 static void setTextMode(FILE *file, int isOutput){ |
151 fflush(out); | 161 if( isOutput ) fflush(file); |
152 _setmode(_fileno(out), _O_TEXT); | 162 _setmode(_fileno(file), _O_TEXT); |
153 } | 163 } |
154 #else | 164 #else |
155 # define setBinaryMode(X) | 165 # define setBinaryMode(X,Y) |
156 # define setTextMode(X) | 166 # define setTextMode(X,Y) |
157 #endif | 167 #endif |
158 | 168 |
159 | 169 |
160 /* True if the timer is enabled */ | 170 /* True if the timer is enabled */ |
161 static int enableTimer = 0; | 171 static int enableTimer = 0; |
162 | 172 |
163 /* Return the current wall-clock time */ | 173 /* Return the current wall-clock time */ |
164 static sqlite3_int64 timeOfDay(void){ | 174 static sqlite3_int64 timeOfDay(void){ |
165 static sqlite3_vfs *clockVfs = 0; | 175 static sqlite3_vfs *clockVfs = 0; |
166 sqlite3_int64 t; | 176 sqlite3_int64 t; |
(...skipping 30 matching lines...) Expand all Loading... |
197 */ | 207 */ |
198 static void beginTimer(void){ | 208 static void beginTimer(void){ |
199 if( enableTimer ){ | 209 if( enableTimer ){ |
200 getrusage(RUSAGE_SELF, &sBegin); | 210 getrusage(RUSAGE_SELF, &sBegin); |
201 iBegin = timeOfDay(); | 211 iBegin = timeOfDay(); |
202 } | 212 } |
203 } | 213 } |
204 | 214 |
205 /* Return the difference of two time_structs in seconds */ | 215 /* Return the difference of two time_structs in seconds */ |
206 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ | 216 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ |
207 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + | 217 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + |
208 (double)(pEnd->tv_sec - pStart->tv_sec); | 218 (double)(pEnd->tv_sec - pStart->tv_sec); |
209 } | 219 } |
210 | 220 |
211 /* | 221 /* |
212 ** Print the timing results. | 222 ** Print the timing results. |
213 */ | 223 */ |
214 static void endTimer(void){ | 224 static void endTimer(void){ |
215 if( enableTimer ){ | 225 if( enableTimer ){ |
216 sqlite3_int64 iEnd = timeOfDay(); | 226 sqlite3_int64 iEnd = timeOfDay(); |
217 struct rusage sEnd; | 227 struct rusage sEnd; |
218 getrusage(RUSAGE_SELF, &sEnd); | 228 getrusage(RUSAGE_SELF, &sEnd); |
219 printf("Run Time: real %.3f user %f sys %f\n", | 229 printf("Run Time: real %.3f user %f sys %f\n", |
220 (iEnd - iBegin)*0.001, | 230 (iEnd - iBegin)*0.001, |
221 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), | 231 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), |
222 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); | 232 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); |
223 } | 233 } |
224 } | 234 } |
225 | 235 |
226 #define BEGIN_TIMER beginTimer() | 236 #define BEGIN_TIMER beginTimer() |
227 #define END_TIMER endTimer() | 237 #define END_TIMER endTimer() |
228 #define HAS_TIMER 1 | 238 #define HAS_TIMER 1 |
229 | 239 |
230 #elif (defined(_WIN32) || defined(WIN32)) | 240 #elif (defined(_WIN32) || defined(WIN32)) |
231 | 241 |
232 #include <windows.h> | |
233 | |
234 /* Saved resource information for the beginning of an operation */ | 242 /* Saved resource information for the beginning of an operation */ |
235 static HANDLE hProcess; | 243 static HANDLE hProcess; |
236 static FILETIME ftKernelBegin; | 244 static FILETIME ftKernelBegin; |
237 static FILETIME ftUserBegin; | 245 static FILETIME ftUserBegin; |
238 static sqlite3_int64 ftWallBegin; | 246 static sqlite3_int64 ftWallBegin; |
239 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, | 247 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, |
240 LPFILETIME, LPFILETIME); | 248 LPFILETIME, LPFILETIME); |
241 static GETPROCTIMES getProcessTimesAddr = NULL; | 249 static GETPROCTIMES getProcessTimesAddr = NULL; |
242 | 250 |
243 /* | 251 /* |
(...skipping 10 matching lines...) Expand all Loading... |
254 */ | 262 */ |
255 hProcess = GetCurrentProcess(); | 263 hProcess = GetCurrentProcess(); |
256 if( hProcess ){ | 264 if( hProcess ){ |
257 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); | 265 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); |
258 if( NULL != hinstLib ){ | 266 if( NULL != hinstLib ){ |
259 getProcessTimesAddr = | 267 getProcessTimesAddr = |
260 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); | 268 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); |
261 if( NULL != getProcessTimesAddr ){ | 269 if( NULL != getProcessTimesAddr ){ |
262 return 1; | 270 return 1; |
263 } | 271 } |
264 FreeLibrary(hinstLib); | 272 FreeLibrary(hinstLib); |
265 } | 273 } |
266 } | 274 } |
267 } | 275 } |
268 return 0; | 276 return 0; |
269 } | 277 } |
270 | 278 |
271 /* | 279 /* |
272 ** Begin timing an operation | 280 ** Begin timing an operation |
273 */ | 281 */ |
274 static void beginTimer(void){ | 282 static void beginTimer(void){ |
(...skipping 25 matching lines...) Expand all Loading... |
300 timeDiff(&ftUserBegin, &ftUserEnd), | 308 timeDiff(&ftUserBegin, &ftUserEnd), |
301 timeDiff(&ftKernelBegin, &ftKernelEnd)); | 309 timeDiff(&ftKernelBegin, &ftKernelEnd)); |
302 } | 310 } |
303 } | 311 } |
304 | 312 |
305 #define BEGIN_TIMER beginTimer() | 313 #define BEGIN_TIMER beginTimer() |
306 #define END_TIMER endTimer() | 314 #define END_TIMER endTimer() |
307 #define HAS_TIMER hasTimer() | 315 #define HAS_TIMER hasTimer() |
308 | 316 |
309 #else | 317 #else |
310 #define BEGIN_TIMER | 318 #define BEGIN_TIMER |
311 #define END_TIMER | 319 #define END_TIMER |
312 #define HAS_TIMER 0 | 320 #define HAS_TIMER 0 |
313 #endif | 321 #endif |
314 | 322 |
315 /* | 323 /* |
316 ** Used to prevent warnings about unused parameters | 324 ** Used to prevent warnings about unused parameters |
317 */ | 325 */ |
318 #define UNUSED_PARAMETER(x) (void)(x) | 326 #define UNUSED_PARAMETER(x) (void)(x) |
319 | 327 |
320 /* | 328 /* |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 static char *Argv0; | 363 static char *Argv0; |
356 | 364 |
357 /* | 365 /* |
358 ** Prompt strings. Initialized in main. Settable with | 366 ** Prompt strings. Initialized in main. Settable with |
359 ** .prompt main continue | 367 ** .prompt main continue |
360 */ | 368 */ |
361 static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ | 369 static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ |
362 static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ | 370 static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ |
363 | 371 |
364 /* | 372 /* |
| 373 ** Render output like fprintf(). Except, if the output is going to the |
| 374 ** console and if this is running on a Windows machine, translate the |
| 375 ** output from UTF-8 into MBCS. |
| 376 */ |
| 377 #if defined(_WIN32) || defined(WIN32) |
| 378 void utf8_printf(FILE *out, const char *zFormat, ...){ |
| 379 va_list ap; |
| 380 va_start(ap, zFormat); |
| 381 if( stdout_is_console && (out==stdout || out==stderr) ){ |
| 382 char *z1 = sqlite3_vmprintf(zFormat, ap); |
| 383 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); |
| 384 sqlite3_free(z1); |
| 385 fputs(z2, out); |
| 386 sqlite3_free(z2); |
| 387 }else{ |
| 388 vfprintf(out, zFormat, ap); |
| 389 } |
| 390 va_end(ap); |
| 391 } |
| 392 #elif !defined(utf8_printf) |
| 393 # define utf8_printf fprintf |
| 394 #endif |
| 395 |
| 396 /* |
| 397 ** Render output like fprintf(). This should not be used on anything that |
| 398 ** includes string formatting (e.g. "%s"). |
| 399 */ |
| 400 #if !defined(raw_printf) |
| 401 # define raw_printf fprintf |
| 402 #endif |
| 403 |
| 404 /* |
365 ** Write I/O traces to the following stream. | 405 ** Write I/O traces to the following stream. |
366 */ | 406 */ |
367 #ifdef SQLITE_ENABLE_IOTRACE | 407 #ifdef SQLITE_ENABLE_IOTRACE |
368 static FILE *iotrace = 0; | 408 static FILE *iotrace = 0; |
369 #endif | 409 #endif |
370 | 410 |
371 /* | 411 /* |
372 ** This routine works like printf in that its first argument is a | 412 ** This routine works like printf in that its first argument is a |
373 ** format string and subsequent arguments are values to be substituted | 413 ** format string and subsequent arguments are values to be substituted |
374 ** in place of % fields. The result of formatting this string | 414 ** in place of % fields. The result of formatting this string |
375 ** is written to iotrace. | 415 ** is written to iotrace. |
376 */ | 416 */ |
377 #ifdef SQLITE_ENABLE_IOTRACE | 417 #ifdef SQLITE_ENABLE_IOTRACE |
378 static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ | 418 static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ |
379 va_list ap; | 419 va_list ap; |
380 char *z; | 420 char *z; |
381 if( iotrace==0 ) return; | 421 if( iotrace==0 ) return; |
382 va_start(ap, zFormat); | 422 va_start(ap, zFormat); |
383 z = sqlite3_vmprintf(zFormat, ap); | 423 z = sqlite3_vmprintf(zFormat, ap); |
384 va_end(ap); | 424 va_end(ap); |
385 fprintf(iotrace, "%s", z); | 425 utf8_printf(iotrace, "%s", z); |
386 sqlite3_free(z); | 426 sqlite3_free(z); |
387 } | 427 } |
388 #endif | 428 #endif |
389 | 429 |
390 | 430 |
391 /* | 431 /* |
392 ** Determines if a string is a number of not. | 432 ** Determines if a string is a number of not. |
393 */ | 433 */ |
394 static int isNumber(const char *z, int *realnum){ | 434 static int isNumber(const char *z, int *realnum){ |
395 if( *z=='-' || *z=='+' ) z++; | 435 if( *z=='-' || *z=='+' ) z++; |
(...skipping 13 matching lines...) Expand all Loading... |
409 z++; | 449 z++; |
410 if( *z=='+' || *z=='-' ) z++; | 450 if( *z=='+' || *z=='-' ) z++; |
411 if( !IsDigit(*z) ) return 0; | 451 if( !IsDigit(*z) ) return 0; |
412 while( IsDigit(*z) ){ z++; } | 452 while( IsDigit(*z) ){ z++; } |
413 if( realnum ) *realnum = 1; | 453 if( realnum ) *realnum = 1; |
414 } | 454 } |
415 return *z==0; | 455 return *z==0; |
416 } | 456 } |
417 | 457 |
418 /* | 458 /* |
419 ** A global char* and an SQL function to access its current value | 459 ** A global char* and an SQL function to access its current value |
420 ** from within an SQL statement. This program used to use the | 460 ** from within an SQL statement. This program used to use the |
421 ** sqlite_exec_printf() API to substitue a string into an SQL statement. | 461 ** 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 | 462 ** 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 | 463 ** 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. | 464 ** of work. Instead just use this hack, which is quite harmless. |
425 */ | 465 */ |
426 static const char *zShellStatic = 0; | 466 static const char *zShellStatic = 0; |
427 static void shellstaticFunc( | 467 static void shellstaticFunc( |
428 sqlite3_context *context, | 468 sqlite3_context *context, |
429 int argc, | 469 int argc, |
430 sqlite3_value **argv | 470 sqlite3_value **argv |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 } | 516 } |
477 while( zLine[n] ) n++; | 517 while( zLine[n] ) n++; |
478 if( n>0 && zLine[n-1]=='\n' ){ | 518 if( n>0 && zLine[n-1]=='\n' ){ |
479 n--; | 519 n--; |
480 if( n>0 && zLine[n-1]=='\r' ) n--; | 520 if( n>0 && zLine[n-1]=='\r' ) n--; |
481 zLine[n] = 0; | 521 zLine[n] = 0; |
482 break; | 522 break; |
483 } | 523 } |
484 } | 524 } |
485 #if defined(_WIN32) || defined(WIN32) | 525 #if defined(_WIN32) || defined(WIN32) |
486 /* For interactive input on Windows systems, translate the | 526 /* For interactive input on Windows systems, translate the |
487 ** multi-byte characterset characters into UTF-8. */ | 527 ** multi-byte characterset characters into UTF-8. */ |
488 if( stdin_is_interactive ){ | 528 if( stdin_is_interactive && in==stdin ){ |
489 extern char *sqlite3_win32_mbcs_to_utf8(const char*); | 529 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); |
490 char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine); | |
491 if( zTrans ){ | 530 if( zTrans ){ |
492 int nTrans = strlen30(zTrans)+1; | 531 int nTrans = strlen30(zTrans)+1; |
493 if( nTrans>nLine ){ | 532 if( nTrans>nLine ){ |
494 zLine = realloc(zLine, nTrans); | 533 zLine = realloc(zLine, nTrans); |
495 if( zLine==0 ){ | 534 if( zLine==0 ){ |
496 sqlite3_free(zTrans); | 535 sqlite3_free(zTrans); |
497 return 0; | 536 return 0; |
498 } | 537 } |
499 } | 538 } |
500 memcpy(zLine, zTrans, nTrans); | 539 memcpy(zLine, zTrans, nTrans); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 zResult = local_getline(zPrior, stdin); | 571 zResult = local_getline(zPrior, stdin); |
533 #else | 572 #else |
534 free(zPrior); | 573 free(zPrior); |
535 zResult = shell_readline(zPrompt); | 574 zResult = shell_readline(zPrompt); |
536 if( zResult && *zResult ) shell_add_history(zResult); | 575 if( zResult && *zResult ) shell_add_history(zResult); |
537 #endif | 576 #endif |
538 } | 577 } |
539 return zResult; | 578 return zResult; |
540 } | 579 } |
541 | 580 |
| 581 #if defined(SQLITE_ENABLE_SESSION) |
542 /* | 582 /* |
543 ** Render output like fprintf(). Except, if the output is going to the | 583 ** State information for a single open session |
544 ** console and if this is running on a Windows machine, translate the | |
545 ** output from UTF-8 into MBCS. | |
546 */ | 584 */ |
547 #if defined(_WIN32) || defined(WIN32) | 585 typedef struct OpenSession OpenSession; |
548 void utf8_printf(FILE *out, const char *zFormat, ...){ | 586 struct OpenSession { |
549 va_list ap; | 587 char *zName; /* Symbolic name for this session */ |
550 va_start(ap, zFormat); | 588 int nFilter; /* Number of xFilter rejection GLOB patterns */ |
551 if( stdout_is_console && (out==stdout || out==stderr) ){ | 589 char **azFilter; /* Array of xFilter rejection GLOB patterns */ |
552 extern char *sqlite3_win32_utf8_to_mbcs(const char*); | 590 sqlite3_session *p; /* The open session */ |
553 char *z1 = sqlite3_vmprintf(zFormat, ap); | 591 }; |
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 | 592 #endif |
566 | 593 |
567 /* | 594 /* |
568 ** Render output like fprintf(). This should not be used on anything that | 595 ** Shell output mode information from before ".explain on", |
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" | 596 ** saved so that it can be restored by ".explain off" |
578 */ | 597 */ |
579 typedef struct SavedModeInfo SavedModeInfo; | 598 typedef struct SavedModeInfo SavedModeInfo; |
580 struct SavedModeInfo { | 599 struct SavedModeInfo { |
581 int valid; /* Is there legit data in here? */ | 600 int valid; /* Is there legit data in here? */ |
582 int mode; /* Mode prior to ".explain on" */ | 601 int mode; /* Mode prior to ".explain on" */ |
583 int showHeader; /* The ".header" setting prior to ".explain on" */ | 602 int showHeader; /* The ".header" setting prior to ".explain on" */ |
584 int colWidth[100]; /* Column widths prior to ".explain on" */ | 603 int colWidth[100]; /* Column widths prior to ".explain on" */ |
585 }; | 604 }; |
586 | 605 |
587 /* | 606 /* |
588 ** State information about the database connection is contained in an | 607 ** State information about the database connection is contained in an |
589 ** instance of the following structure. | 608 ** instance of the following structure. |
590 */ | 609 */ |
591 typedef struct ShellState ShellState; | 610 typedef struct ShellState ShellState; |
592 struct ShellState { | 611 struct ShellState { |
593 sqlite3 *db; /* The database */ | 612 sqlite3 *db; /* The database */ |
594 int echoOn; /* True to echo input commands */ | 613 int echoOn; /* True to echo input commands */ |
| 614 int autoExplain; /* Automatically turn on .explain mode */ |
595 int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ | 615 int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
596 int statsOn; /* True to display memory stats before each finalize */ | 616 int statsOn; /* True to display memory stats before each finalize */ |
597 int scanstatsOn; /* True to display scan stats before each finalize */ | 617 int scanstatsOn; /* True to display scan stats before each finalize */ |
598 int countChanges; /* True to display change counts */ | 618 int countChanges; /* True to display change counts */ |
599 int backslashOn; /* Resolve C-style \x escapes in SQL input text */ | 619 int backslashOn; /* Resolve C-style \x escapes in SQL input text */ |
600 int outCount; /* Revert to stdout when reaching zero */ | 620 int outCount; /* Revert to stdout when reaching zero */ |
601 int cnt; /* Number of records displayed so far */ | 621 int cnt; /* Number of records displayed so far */ |
602 FILE *out; /* Write results here */ | 622 FILE *out; /* Write results here */ |
603 FILE *traceOut; /* Output for sqlite3_trace() */ | 623 FILE *traceOut; /* Output for sqlite3_trace() */ |
604 int nErr; /* Number of errors seen */ | 624 int nErr; /* Number of errors seen */ |
605 int mode; /* An output mode setting */ | 625 int mode; /* An output mode setting */ |
| 626 int cMode; /* temporary output mode for the current query */ |
| 627 int normalMode; /* Output mode before ".explain on" */ |
606 int writableSchema; /* True if PRAGMA writable_schema=ON */ | 628 int writableSchema; /* True if PRAGMA writable_schema=ON */ |
607 int showHeader; /* True to show column names in List or Column mode */ | 629 int showHeader; /* True to show column names in List or Column mode */ |
| 630 int nCheck; /* Number of ".check" commands run */ |
608 unsigned shellFlgs; /* Various flags */ | 631 unsigned shellFlgs; /* Various flags */ |
609 char *zDestTable; /* Name of destination table when MODE_Insert */ | 632 char *zDestTable; /* Name of destination table when MODE_Insert */ |
| 633 char zTestcase[30]; /* Name of current test case */ |
610 char colSeparator[20]; /* Column separator character for several modes */ | 634 char colSeparator[20]; /* Column separator character for several modes */ |
611 char rowSeparator[20]; /* Row separator character for MODE_Ascii */ | 635 char rowSeparator[20]; /* Row separator character for MODE_Ascii */ |
612 int colWidth[100]; /* Requested width of each column when in column mode*/ | 636 int colWidth[100]; /* Requested width of each column when in column mode*/ |
613 int actualWidth[100]; /* Actual width of each column */ | 637 int actualWidth[100]; /* Actual width of each column */ |
614 char nullValue[20]; /* The text to print when a NULL comes back from | 638 char nullValue[20]; /* The text to print when a NULL comes back from |
615 ** the database */ | 639 ** the database */ |
616 SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ | |
617 char outfile[FILENAME_MAX]; /* Filename for *out */ | 640 char outfile[FILENAME_MAX]; /* Filename for *out */ |
618 const char *zDbFilename; /* name of the database file */ | 641 const char *zDbFilename; /* name of the database file */ |
619 char *zFreeOnClose; /* Filename to free when closing */ | 642 char *zFreeOnClose; /* Filename to free when closing */ |
620 const char *zVfs; /* Name of VFS to use */ | 643 const char *zVfs; /* Name of VFS to use */ |
621 sqlite3_stmt *pStmt; /* Current statement if any. */ | 644 sqlite3_stmt *pStmt; /* Current statement if any. */ |
622 FILE *pLog; /* Write log output here */ | 645 FILE *pLog; /* Write log output here */ |
623 int *aiIndent; /* Array of indents used in MODE_Explain */ | 646 int *aiIndent; /* Array of indents used in MODE_Explain */ |
624 int nIndent; /* Size of array aiIndent[] */ | 647 int nIndent; /* Size of array aiIndent[] */ |
625 int iIndent; /* Index of current op in aiIndent[] */ | 648 int iIndent; /* Index of current op in aiIndent[] */ |
| 649 #if defined(SQLITE_ENABLE_SESSION) |
| 650 int nSession; /* Number of active sessions */ |
| 651 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ |
| 652 #endif |
626 }; | 653 }; |
627 | 654 |
628 /* | 655 /* |
629 ** These are the allowed shellFlgs values | 656 ** These are the allowed shellFlgs values |
630 */ | 657 */ |
631 #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ | 658 #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ |
632 #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ | 659 #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ |
633 #define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ | 660 #define SHFLG_Lookaside 0x00004 /* Lookaside memory is used */ |
634 | 661 |
635 /* | 662 /* |
636 ** These are the allowed modes. | 663 ** These are the allowed modes. |
637 */ | 664 */ |
638 #define MODE_Line 0 /* One column per line. Blank line between records */ | 665 #define MODE_Line 0 /* One column per line. Blank line between records */ |
639 #define MODE_Column 1 /* One record per line in neat columns */ | 666 #define MODE_Column 1 /* One record per line in neat columns */ |
640 #define MODE_List 2 /* One record per line with a separator */ | 667 #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 */ | 668 #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
642 #define MODE_Html 4 /* Generate an XHTML table */ | 669 #define MODE_Html 4 /* Generate an XHTML table */ |
643 #define MODE_Insert 5 /* Generate SQL "insert" statements */ | 670 #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
644 #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ | 671 #define MODE_Quote 6 /* Quote values as for SQL */ |
645 #define MODE_Csv 7 /* Quote strings, numbers are plain */ | 672 #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ |
646 #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ | 673 #define MODE_Csv 8 /* Quote strings, numbers are plain */ |
647 #define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ | 674 #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ |
| 675 #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 676 #define MODE_Pretty 11 /* Pretty-print schemas */ |
648 | 677 |
649 static const char *modeDescr[] = { | 678 static const char *modeDescr[] = { |
650 "line", | 679 "line", |
651 "column", | 680 "column", |
652 "list", | 681 "list", |
653 "semi", | 682 "semi", |
654 "html", | 683 "html", |
655 "insert", | 684 "insert", |
| 685 "quote", |
656 "tcl", | 686 "tcl", |
657 "csv", | 687 "csv", |
658 "explain", | 688 "explain", |
659 "ascii", | 689 "ascii", |
| 690 "prettyprint", |
660 }; | 691 }; |
661 | 692 |
662 /* | 693 /* |
663 ** These are the column/row/line separators used by the various | 694 ** These are the column/row/line separators used by the various |
664 ** import/export modes. | 695 ** import/export modes. |
665 */ | 696 */ |
666 #define SEP_Column "|" | 697 #define SEP_Column "|" |
667 #define SEP_Row "\n" | 698 #define SEP_Row "\n" |
668 #define SEP_Tab "\t" | 699 #define SEP_Tab "\t" |
669 #define SEP_Space " " | 700 #define SEP_Space " " |
(...skipping 27 matching lines...) Expand all Loading... |
697 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); } | 728 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); } |
698 raw_printf(out,"'"); | 729 raw_printf(out,"'"); |
699 } | 730 } |
700 | 731 |
701 /* | 732 /* |
702 ** Output the given string as a quoted string using SQL quoting conventions. | 733 ** Output the given string as a quoted string using SQL quoting conventions. |
703 */ | 734 */ |
704 static void output_quoted_string(FILE *out, const char *z){ | 735 static void output_quoted_string(FILE *out, const char *z){ |
705 int i; | 736 int i; |
706 int nSingle = 0; | 737 int nSingle = 0; |
707 setBinaryMode(out); | 738 setBinaryMode(out, 1); |
708 for(i=0; z[i]; i++){ | 739 for(i=0; z[i]; i++){ |
709 if( z[i]=='\'' ) nSingle++; | 740 if( z[i]=='\'' ) nSingle++; |
710 } | 741 } |
711 if( nSingle==0 ){ | 742 if( nSingle==0 ){ |
712 utf8_printf(out,"'%s'",z); | 743 utf8_printf(out,"'%s'",z); |
713 }else{ | 744 }else{ |
714 raw_printf(out,"'"); | 745 raw_printf(out,"'"); |
715 while( *z ){ | 746 while( *z ){ |
716 for(i=0; z[i] && z[i]!='\''; i++){} | 747 for(i=0; z[i] && z[i]!='\''; i++){} |
717 if( i==0 ){ | 748 if( i==0 ){ |
718 raw_printf(out,"''"); | 749 raw_printf(out,"''"); |
719 z++; | 750 z++; |
720 }else if( z[i]=='\'' ){ | 751 }else if( z[i]=='\'' ){ |
721 utf8_printf(out,"%.*s''",i,z); | 752 utf8_printf(out,"%.*s''",i,z); |
722 z += i+1; | 753 z += i+1; |
723 }else{ | 754 }else{ |
724 utf8_printf(out,"%s",z); | 755 utf8_printf(out,"%s",z); |
725 break; | 756 break; |
726 } | 757 } |
727 } | 758 } |
728 raw_printf(out,"'"); | 759 raw_printf(out,"'"); |
729 } | 760 } |
730 setTextMode(out); | 761 setTextMode(out, 1); |
731 } | 762 } |
732 | 763 |
733 /* | 764 /* |
734 ** Output the given string as a quoted according to C or TCL quoting rules. | 765 ** Output the given string as a quoted according to C or TCL quoting rules. |
735 */ | 766 */ |
736 static void output_c_string(FILE *out, const char *z){ | 767 static void output_c_string(FILE *out, const char *z){ |
737 unsigned int c; | 768 unsigned int c; |
738 fputc('"', out); | 769 fputc('"', out); |
739 while( (c = *(z++))!=0 ){ | 770 while( (c = *(z++))!=0 ){ |
740 if( c=='\\' ){ | 771 if( c=='\\' ){ |
(...skipping 21 matching lines...) Expand all Loading... |
762 } | 793 } |
763 | 794 |
764 /* | 795 /* |
765 ** Output the given string with characters that are special to | 796 ** Output the given string with characters that are special to |
766 ** HTML escaped. | 797 ** HTML escaped. |
767 */ | 798 */ |
768 static void output_html_string(FILE *out, const char *z){ | 799 static void output_html_string(FILE *out, const char *z){ |
769 int i; | 800 int i; |
770 if( z==0 ) z = ""; | 801 if( z==0 ) z = ""; |
771 while( *z ){ | 802 while( *z ){ |
772 for(i=0; z[i] | 803 for(i=0; z[i] |
773 && z[i]!='<' | 804 && z[i]!='<' |
774 && z[i]!='&' | 805 && z[i]!='&' |
775 && z[i]!='>' | 806 && z[i]!='>' |
776 && z[i]!='\"' | 807 && z[i]!='\"' |
777 && z[i]!='\''; | 808 && z[i]!='\''; |
778 i++){} | 809 i++){} |
779 if( i>0 ){ | 810 if( i>0 ){ |
780 utf8_printf(out,"%.*s",i,z); | 811 utf8_printf(out,"%.*s",i,z); |
781 } | 812 } |
782 if( z[i]=='<' ){ | 813 if( z[i]=='<' ){ |
783 raw_printf(out,"<"); | 814 raw_printf(out,"<"); |
784 }else if( z[i]=='&' ){ | 815 }else if( z[i]=='&' ){ |
785 raw_printf(out,"&"); | 816 raw_printf(out,"&"); |
786 }else if( z[i]=='>' ){ | 817 }else if( z[i]=='>' ){ |
787 raw_printf(out,">"); | 818 raw_printf(out,">"); |
788 }else if( z[i]=='\"' ){ | 819 }else if( z[i]=='\"' ){ |
789 raw_printf(out,"""); | 820 raw_printf(out,"""); |
790 }else if( z[i]=='\'' ){ | 821 }else if( z[i]=='\'' ){ |
791 raw_printf(out,"'"); | 822 raw_printf(out,"'"); |
792 }else{ | 823 }else{ |
793 break; | 824 break; |
794 } | 825 } |
795 z += i + 1; | 826 z += i + 1; |
796 } | 827 } |
797 } | 828 } |
798 | 829 |
799 /* | 830 /* |
800 ** If a field contains any character identified by a 1 in the following | 831 ** If a field contains any character identified by a 1 in the following |
801 ** array, then the string must be quoted for CSV. | 832 ** array, then the string must be quoted for CSV. |
802 */ | 833 */ |
803 static const char needCsvQuote[] = { | 834 static const char needCsvQuote[] = { |
804 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 835 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, | 836 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, | 837 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, | 838 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, | 839 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, | 840 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, | 841 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, | 842 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, | 843 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, | 844 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, | 845 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, | 846 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, | 847 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, | 848 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, | 849 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, | 850 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
820 }; | 851 }; |
821 | 852 |
822 /* | 853 /* |
823 ** Output a single term of CSV. Actually, p->colSeparator is used for | 854 ** 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 | 855 ** the separator, which may or may not be a comma. p->nullValue is |
825 ** the null value. Strings are quoted if necessary. The separator | 856 ** the null value. Strings are quoted if necessary. The separator |
826 ** is only issued if bSep is true. | 857 ** is only issued if bSep is true. |
827 */ | 858 */ |
828 static void output_csv(ShellState *p, const char *z, int bSep){ | 859 static void output_csv(ShellState *p, const char *z, int bSep){ |
829 FILE *out = p->out; | 860 FILE *out = p->out; |
830 if( z==0 ){ | 861 if( z==0 ){ |
831 utf8_printf(out,"%s",p->nullValue); | 862 utf8_printf(out,"%s",p->nullValue); |
832 }else{ | 863 }else{ |
833 int i; | 864 int i; |
834 int nSep = strlen30(p->colSeparator); | 865 int nSep = strlen30(p->colSeparator); |
835 for(i=0; z[i]; i++){ | 866 for(i=0; z[i]; i++){ |
836 if( needCsvQuote[((unsigned char*)z)[i]] | 867 if( needCsvQuote[((unsigned char*)z)[i]] |
837 || (z[i]==p->colSeparator[0] && | 868 || (z[i]==p->colSeparator[0] && |
838 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ | 869 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ |
839 i = 0; | 870 i = 0; |
840 break; | 871 break; |
841 } | 872 } |
842 } | 873 } |
843 if( i==0 ){ | 874 if( i==0 ){ |
844 putc('"', out); | 875 putc('"', out); |
845 for(i=0; z[i]; i++){ | 876 for(i=0; z[i]; i++){ |
846 if( z[i]=='"' ) putc('"', out); | 877 if( z[i]=='"' ) putc('"', out); |
847 putc(z[i], out); | 878 putc(z[i], out); |
(...skipping 13 matching lines...) Expand all Loading... |
861 ** This routine runs when the user presses Ctrl-C | 892 ** This routine runs when the user presses Ctrl-C |
862 */ | 893 */ |
863 static void interrupt_handler(int NotUsed){ | 894 static void interrupt_handler(int NotUsed){ |
864 UNUSED_PARAMETER(NotUsed); | 895 UNUSED_PARAMETER(NotUsed); |
865 seenInterrupt++; | 896 seenInterrupt++; |
866 if( seenInterrupt>2 ) exit(1); | 897 if( seenInterrupt>2 ) exit(1); |
867 if( globalDb ) sqlite3_interrupt(globalDb); | 898 if( globalDb ) sqlite3_interrupt(globalDb); |
868 } | 899 } |
869 #endif | 900 #endif |
870 | 901 |
| 902 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 903 /* |
| 904 ** When the ".auth ON" is set, the following authorizer callback is |
| 905 ** invoked. It always returns SQLITE_OK. |
| 906 */ |
| 907 static int shellAuth( |
| 908 void *pClientData, |
| 909 int op, |
| 910 const char *zA1, |
| 911 const char *zA2, |
| 912 const char *zA3, |
| 913 const char *zA4 |
| 914 ){ |
| 915 ShellState *p = (ShellState*)pClientData; |
| 916 static const char *azAction[] = { 0, |
| 917 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX", |
| 918 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW", |
| 919 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE", |
| 920 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX", |
| 921 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW", |
| 922 "DROP_TRIGGER", "DROP_VIEW", "INSERT", |
| 923 "PRAGMA", "READ", "SELECT", |
| 924 "TRANSACTION", "UPDATE", "ATTACH", |
| 925 "DETACH", "ALTER_TABLE", "REINDEX", |
| 926 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE", |
| 927 "FUNCTION", "SAVEPOINT", "RECURSIVE" |
| 928 }; |
| 929 int i; |
| 930 const char *az[4]; |
| 931 az[0] = zA1; |
| 932 az[1] = zA2; |
| 933 az[2] = zA3; |
| 934 az[3] = zA4; |
| 935 utf8_printf(p->out, "authorizer: %s", azAction[op]); |
| 936 for(i=0; i<4; i++){ |
| 937 raw_printf(p->out, " "); |
| 938 if( az[i] ){ |
| 939 output_c_string(p->out, az[i]); |
| 940 }else{ |
| 941 raw_printf(p->out, "NULL"); |
| 942 } |
| 943 } |
| 944 raw_printf(p->out, "\n"); |
| 945 return SQLITE_OK; |
| 946 } |
| 947 #endif |
| 948 |
871 /* | 949 /* |
| 950 ** Print a schema statement. Part of MODE_Semi and MODE_Pretty output. |
| 951 ** |
| 952 ** This routine converts some CREATE TABLE statements for shadow tables |
| 953 ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements. |
| 954 */ |
| 955 static void printSchemaLine(FILE *out, const char *z, const char *zTail){ |
| 956 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ |
| 957 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); |
| 958 }else{ |
| 959 utf8_printf(out, "%s%s", z, zTail); |
| 960 } |
| 961 } |
| 962 static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ |
| 963 char c = z[n]; |
| 964 z[n] = 0; |
| 965 printSchemaLine(out, z, zTail); |
| 966 z[n] = c; |
| 967 } |
| 968 |
| 969 /* |
872 ** This is the callback routine that the shell | 970 ** This is the callback routine that the shell |
873 ** invokes for each row of a query result. | 971 ** invokes for each row of a query result. |
874 */ | 972 */ |
875 static int shell_callback( | 973 static int shell_callback( |
876 void *pArg, | 974 void *pArg, |
877 int nArg, /* Number of result columns */ | 975 int nArg, /* Number of result columns */ |
878 char **azArg, /* Text of each result column */ | 976 char **azArg, /* Text of each result column */ |
879 char **azCol, /* Column names */ | 977 char **azCol, /* Column names */ |
880 int *aiType /* Column types */ | 978 int *aiType /* Column types */ |
881 ){ | 979 ){ |
882 int i; | 980 int i; |
883 ShellState *p = (ShellState*)pArg; | 981 ShellState *p = (ShellState*)pArg; |
884 | 982 |
885 switch( p->mode ){ | 983 switch( p->cMode ){ |
886 case MODE_Line: { | 984 case MODE_Line: { |
887 int w = 5; | 985 int w = 5; |
888 if( azArg==0 ) break; | 986 if( azArg==0 ) break; |
889 for(i=0; i<nArg; i++){ | 987 for(i=0; i<nArg; i++){ |
890 int len = strlen30(azCol[i] ? azCol[i] : ""); | 988 int len = strlen30(azCol[i] ? azCol[i] : ""); |
891 if( len>w ) w = len; | 989 if( len>w ) w = len; |
892 } | 990 } |
893 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); | 991 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); |
894 for(i=0; i<nArg; i++){ | 992 for(i=0; i<nArg; i++){ |
895 utf8_printf(p->out,"%*s = %s%s", w, azCol[i], | 993 utf8_printf(p->out,"%*s = %s%s", w, azCol[i], |
896 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); | 994 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); |
897 } | 995 } |
898 break; | 996 break; |
899 } | 997 } |
900 case MODE_Explain: | 998 case MODE_Explain: |
901 case MODE_Column: { | 999 case MODE_Column: { |
| 1000 static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13}; |
| 1001 const int *colWidth; |
| 1002 int showHdr; |
| 1003 char *rowSep; |
| 1004 if( p->cMode==MODE_Column ){ |
| 1005 colWidth = p->colWidth; |
| 1006 showHdr = p->showHeader; |
| 1007 rowSep = p->rowSeparator; |
| 1008 }else{ |
| 1009 colWidth = aExplainWidths; |
| 1010 showHdr = 1; |
| 1011 rowSep = SEP_Row; |
| 1012 } |
902 if( p->cnt++==0 ){ | 1013 if( p->cnt++==0 ){ |
903 for(i=0; i<nArg; i++){ | 1014 for(i=0; i<nArg; i++){ |
904 int w, n; | 1015 int w, n; |
905 if( i<ArraySize(p->colWidth) ){ | 1016 if( i<ArraySize(p->colWidth) ){ |
906 w = p->colWidth[i]; | 1017 w = colWidth[i]; |
907 }else{ | 1018 }else{ |
908 w = 0; | 1019 w = 0; |
909 } | 1020 } |
910 if( w==0 ){ | 1021 if( w==0 ){ |
911 w = strlen30(azCol[i] ? azCol[i] : ""); | 1022 w = strlen30(azCol[i] ? azCol[i] : ""); |
912 if( w<10 ) w = 10; | 1023 if( w<10 ) w = 10; |
913 n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); | 1024 n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); |
914 if( w<n ) w = n; | 1025 if( w<n ) w = n; |
915 } | 1026 } |
916 if( i<ArraySize(p->actualWidth) ){ | 1027 if( i<ArraySize(p->actualWidth) ){ |
917 p->actualWidth[i] = w; | 1028 p->actualWidth[i] = w; |
918 } | 1029 } |
919 if( p->showHeader ){ | 1030 if( showHdr ){ |
920 if( w<0 ){ | 1031 if( w<0 ){ |
921 utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], | 1032 utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], |
922 i==nArg-1 ? p->rowSeparator : " "); | 1033 i==nArg-1 ? rowSep : " "); |
923 }else{ | 1034 }else{ |
924 utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], | 1035 utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], |
925 i==nArg-1 ? p->rowSeparator : " "); | 1036 i==nArg-1 ? rowSep : " "); |
926 } | 1037 } |
927 } | 1038 } |
928 } | 1039 } |
929 if( p->showHeader ){ | 1040 if( showHdr ){ |
930 for(i=0; i<nArg; i++){ | 1041 for(i=0; i<nArg; i++){ |
931 int w; | 1042 int w; |
932 if( i<ArraySize(p->actualWidth) ){ | 1043 if( i<ArraySize(p->actualWidth) ){ |
933 w = p->actualWidth[i]; | 1044 w = p->actualWidth[i]; |
934 if( w<0 ) w = -w; | 1045 if( w<0 ) w = -w; |
935 }else{ | 1046 }else{ |
936 w = 10; | 1047 w = 10; |
937 } | 1048 } |
938 utf8_printf(p->out,"%-*.*s%s",w,w, | 1049 utf8_printf(p->out,"%-*.*s%s",w,w, |
939 "----------------------------------------------------------" | 1050 "----------------------------------------------------------" |
940 "----------------------------------------------------------", | 1051 "----------------------------------------------------------", |
941 i==nArg-1 ? p->rowSeparator : " "); | 1052 i==nArg-1 ? rowSep : " "); |
942 } | 1053 } |
943 } | 1054 } |
944 } | 1055 } |
945 if( azArg==0 ) break; | 1056 if( azArg==0 ) break; |
946 for(i=0; i<nArg; i++){ | 1057 for(i=0; i<nArg; i++){ |
947 int w; | 1058 int w; |
948 if( i<ArraySize(p->actualWidth) ){ | 1059 if( i<ArraySize(p->actualWidth) ){ |
949 w = p->actualWidth[i]; | 1060 w = p->actualWidth[i]; |
950 }else{ | 1061 }else{ |
951 w = 10; | 1062 w = 10; |
952 } | 1063 } |
953 if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ | 1064 if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ |
954 w = strlen30(azArg[i]); | 1065 w = strlen30(azArg[i]); |
955 } | 1066 } |
956 if( i==1 && p->aiIndent && p->pStmt ){ | 1067 if( i==1 && p->aiIndent && p->pStmt ){ |
957 if( p->iIndent<p->nIndent ){ | 1068 if( p->iIndent<p->nIndent ){ |
958 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); | 1069 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
959 } | 1070 } |
960 p->iIndent++; | 1071 p->iIndent++; |
961 } | 1072 } |
962 if( w<0 ){ | 1073 if( w<0 ){ |
963 utf8_printf(p->out,"%*.*s%s",-w,-w, | 1074 utf8_printf(p->out,"%*.*s%s",-w,-w, |
964 azArg[i] ? azArg[i] : p->nullValue, | 1075 azArg[i] ? azArg[i] : p->nullValue, |
965 i==nArg-1 ? p->rowSeparator : " "); | 1076 i==nArg-1 ? rowSep : " "); |
966 }else{ | 1077 }else{ |
967 utf8_printf(p->out,"%-*.*s%s",w,w, | 1078 utf8_printf(p->out,"%-*.*s%s",w,w, |
968 azArg[i] ? azArg[i] : p->nullValue, | 1079 azArg[i] ? azArg[i] : p->nullValue, |
969 i==nArg-1 ? p->rowSeparator : " "); | 1080 i==nArg-1 ? rowSep : " "); |
970 } | 1081 } |
971 } | 1082 } |
972 break; | 1083 break; |
973 } | 1084 } |
974 case MODE_Semi: | 1085 case MODE_Semi: { /* .schema and .fullschema output */ |
| 1086 printSchemaLine(p->out, azArg[0], ";\n"); |
| 1087 break; |
| 1088 } |
| 1089 case MODE_Pretty: { /* .schema and .fullschema with --indent */ |
| 1090 char *z; |
| 1091 int j; |
| 1092 int nParen = 0; |
| 1093 char cEnd = 0; |
| 1094 char c; |
| 1095 int nLine = 0; |
| 1096 assert( nArg==1 ); |
| 1097 if( azArg[0]==0 ) break; |
| 1098 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 |
| 1099 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 |
| 1100 ){ |
| 1101 utf8_printf(p->out, "%s;\n", azArg[0]); |
| 1102 break; |
| 1103 } |
| 1104 z = sqlite3_mprintf("%s", azArg[0]); |
| 1105 j = 0; |
| 1106 for(i=0; IsSpace(z[i]); i++){} |
| 1107 for(; (c = z[i])!=0; i++){ |
| 1108 if( IsSpace(c) ){ |
| 1109 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; |
| 1110 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ |
| 1111 j--; |
| 1112 } |
| 1113 z[j++] = c; |
| 1114 } |
| 1115 while( j>0 && IsSpace(z[j-1]) ){ j--; } |
| 1116 z[j] = 0; |
| 1117 if( strlen30(z)>=79 ){ |
| 1118 for(i=j=0; (c = z[i])!=0; i++){ |
| 1119 if( c==cEnd ){ |
| 1120 cEnd = 0; |
| 1121 }else if( c=='"' || c=='\'' || c=='`' ){ |
| 1122 cEnd = c; |
| 1123 }else if( c=='[' ){ |
| 1124 cEnd = ']'; |
| 1125 }else if( c=='(' ){ |
| 1126 nParen++; |
| 1127 }else if( c==')' ){ |
| 1128 nParen--; |
| 1129 if( nLine>0 && nParen==0 && j>0 ){ |
| 1130 printSchemaLineN(p->out, z, j, "\n"); |
| 1131 j = 0; |
| 1132 } |
| 1133 } |
| 1134 z[j++] = c; |
| 1135 if( nParen==1 && (c=='(' || c==',' || c=='\n') ){ |
| 1136 if( c=='\n' ) j--; |
| 1137 printSchemaLineN(p->out, z, j, "\n "); |
| 1138 j = 0; |
| 1139 nLine++; |
| 1140 while( IsSpace(z[i+1]) ){ i++; } |
| 1141 } |
| 1142 } |
| 1143 z[j] = 0; |
| 1144 } |
| 1145 printSchemaLine(p->out, z, ";\n"); |
| 1146 sqlite3_free(z); |
| 1147 break; |
| 1148 } |
975 case MODE_List: { | 1149 case MODE_List: { |
976 if( p->cnt++==0 && p->showHeader ){ | 1150 if( p->cnt++==0 && p->showHeader ){ |
977 for(i=0; i<nArg; i++){ | 1151 for(i=0; i<nArg; i++){ |
978 utf8_printf(p->out,"%s%s",azCol[i], | 1152 utf8_printf(p->out,"%s%s",azCol[i], |
979 i==nArg-1 ? p->rowSeparator : p->colSeparator); | 1153 i==nArg-1 ? p->rowSeparator : p->colSeparator); |
980 } | 1154 } |
981 } | 1155 } |
982 if( azArg==0 ) break; | 1156 if( azArg==0 ) break; |
983 for(i=0; i<nArg; i++){ | 1157 for(i=0; i<nArg; i++){ |
984 char *z = azArg[i]; | 1158 char *z = azArg[i]; |
985 if( z==0 ) z = p->nullValue; | 1159 if( z==0 ) z = p->nullValue; |
986 utf8_printf(p->out, "%s", z); | 1160 utf8_printf(p->out, "%s", z); |
987 if( i<nArg-1 ){ | 1161 if( i<nArg-1 ){ |
988 utf8_printf(p->out, "%s", p->colSeparator); | 1162 utf8_printf(p->out, "%s", p->colSeparator); |
989 }else if( p->mode==MODE_Semi ){ | |
990 utf8_printf(p->out, ";%s", p->rowSeparator); | |
991 }else{ | 1163 }else{ |
992 utf8_printf(p->out, "%s", p->rowSeparator); | 1164 utf8_printf(p->out, "%s", p->rowSeparator); |
993 } | 1165 } |
994 } | 1166 } |
995 break; | 1167 break; |
996 } | 1168 } |
997 case MODE_Html: { | 1169 case MODE_Html: { |
998 if( p->cnt++==0 && p->showHeader ){ | 1170 if( p->cnt++==0 && p->showHeader ){ |
999 raw_printf(p->out,"<TR>"); | 1171 raw_printf(p->out,"<TR>"); |
1000 for(i=0; i<nArg; i++){ | 1172 for(i=0; i<nArg; i++){ |
(...skipping 23 matching lines...) Expand all Loading... |
1024 } | 1196 } |
1025 if( azArg==0 ) break; | 1197 if( azArg==0 ) break; |
1026 for(i=0; i<nArg; i++){ | 1198 for(i=0; i<nArg; i++){ |
1027 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue); | 1199 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue); |
1028 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator); | 1200 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator); |
1029 } | 1201 } |
1030 utf8_printf(p->out, "%s", p->rowSeparator); | 1202 utf8_printf(p->out, "%s", p->rowSeparator); |
1031 break; | 1203 break; |
1032 } | 1204 } |
1033 case MODE_Csv: { | 1205 case MODE_Csv: { |
1034 setBinaryMode(p->out); | 1206 setBinaryMode(p->out, 1); |
1035 if( p->cnt++==0 && p->showHeader ){ | 1207 if( p->cnt++==0 && p->showHeader ){ |
1036 for(i=0; i<nArg; i++){ | 1208 for(i=0; i<nArg; i++){ |
1037 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); | 1209 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); |
1038 } | 1210 } |
1039 utf8_printf(p->out, "%s", p->rowSeparator); | 1211 utf8_printf(p->out, "%s", p->rowSeparator); |
1040 } | 1212 } |
1041 if( nArg>0 ){ | 1213 if( nArg>0 ){ |
1042 for(i=0; i<nArg; i++){ | 1214 for(i=0; i<nArg; i++){ |
1043 output_csv(p, azArg[i], i<nArg-1); | 1215 output_csv(p, azArg[i], i<nArg-1); |
1044 } | 1216 } |
1045 utf8_printf(p->out, "%s", p->rowSeparator); | 1217 utf8_printf(p->out, "%s", p->rowSeparator); |
1046 } | 1218 } |
1047 setTextMode(p->out); | 1219 setTextMode(p->out, 1); |
1048 break; | 1220 break; |
1049 } | 1221 } |
| 1222 case MODE_Quote: |
1050 case MODE_Insert: { | 1223 case MODE_Insert: { |
| 1224 if( azArg==0 ) break; |
| 1225 if( p->cMode==MODE_Insert ){ |
| 1226 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); |
| 1227 if( p->showHeader ){ |
| 1228 raw_printf(p->out,"("); |
| 1229 for(i=0; i<nArg; i++){ |
| 1230 char *zSep = i>0 ? ",": ""; |
| 1231 utf8_printf(p->out, "%s%s", zSep, azCol[i]); |
| 1232 } |
| 1233 raw_printf(p->out,")"); |
| 1234 } |
| 1235 raw_printf(p->out," VALUES("); |
| 1236 }else if( p->cnt==0 && p->showHeader ){ |
| 1237 for(i=0; i<nArg; i++){ |
| 1238 if( i>0 ) raw_printf(p->out, ","); |
| 1239 output_quoted_string(p->out, azCol[i]); |
| 1240 } |
| 1241 raw_printf(p->out,"\n"); |
| 1242 } |
1051 p->cnt++; | 1243 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++){ | 1244 for(i=0; i<nArg; i++){ |
1064 char *zSep = i>0 ? ",": ""; | 1245 char *zSep = i>0 ? ",": ""; |
1065 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ | 1246 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
1066 utf8_printf(p->out,"%sNULL",zSep); | 1247 utf8_printf(p->out,"%sNULL",zSep); |
1067 }else if( aiType && aiType[i]==SQLITE_TEXT ){ | 1248 }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
1068 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); | 1249 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
1069 output_quoted_string(p->out, azArg[i]); | 1250 output_quoted_string(p->out, azArg[i]); |
1070 }else if( aiType && (aiType[i]==SQLITE_INTEGER | 1251 }else if( aiType && (aiType[i]==SQLITE_INTEGER |
1071 || aiType[i]==SQLITE_FLOAT) ){ | 1252 || aiType[i]==SQLITE_FLOAT) ){ |
1072 utf8_printf(p->out,"%s%s",zSep, azArg[i]); | 1253 utf8_printf(p->out,"%s%s",zSep, azArg[i]); |
1073 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ | 1254 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ |
1074 const void *pBlob = sqlite3_column_blob(p->pStmt, i); | 1255 const void *pBlob = sqlite3_column_blob(p->pStmt, i); |
1075 int nBlob = sqlite3_column_bytes(p->pStmt, i); | 1256 int nBlob = sqlite3_column_bytes(p->pStmt, i); |
1076 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); | 1257 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
1077 output_hex_blob(p->out, pBlob, nBlob); | 1258 output_hex_blob(p->out, pBlob, nBlob); |
1078 }else if( isNumber(azArg[i], 0) ){ | 1259 }else if( isNumber(azArg[i], 0) ){ |
1079 utf8_printf(p->out,"%s%s",zSep, azArg[i]); | 1260 utf8_printf(p->out,"%s%s",zSep, azArg[i]); |
1080 }else{ | 1261 }else{ |
1081 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); | 1262 if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
1082 output_quoted_string(p->out, azArg[i]); | 1263 output_quoted_string(p->out, azArg[i]); |
1083 } | 1264 } |
1084 } | 1265 } |
1085 raw_printf(p->out,");\n"); | 1266 raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); |
1086 break; | 1267 break; |
1087 } | 1268 } |
1088 case MODE_Ascii: { | 1269 case MODE_Ascii: { |
1089 if( p->cnt++==0 && p->showHeader ){ | 1270 if( p->cnt++==0 && p->showHeader ){ |
1090 for(i=0; i<nArg; i++){ | 1271 for(i=0; i<nArg; i++){ |
1091 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); | 1272 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); |
1092 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); | 1273 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); |
1093 } | 1274 } |
1094 utf8_printf(p->out, "%s", p->rowSeparator); | 1275 utf8_printf(p->out, "%s", p->rowSeparator); |
1095 } | 1276 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 } | 1331 } |
1151 if( needQuote ) z[n++] = '\''; | 1332 if( needQuote ) z[n++] = '\''; |
1152 z[n] = 0; | 1333 z[n] = 0; |
1153 } | 1334 } |
1154 | 1335 |
1155 /* zIn is either a pointer to a NULL-terminated string in memory obtained | 1336 /* 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 | 1337 ** 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(). | 1338 ** added to zIn, and the result returned in memory obtained from malloc(). |
1158 ** zIn, if it was not NULL, is freed. | 1339 ** zIn, if it was not NULL, is freed. |
1159 ** | 1340 ** |
1160 ** If the third argument, quote, is not '\0', then it is used as a | 1341 ** If the third argument, quote, is not '\0', then it is used as a |
1161 ** quote character for zAppend. | 1342 ** quote character for zAppend. |
1162 */ | 1343 */ |
1163 static char *appendText(char *zIn, char const *zAppend, char quote){ | 1344 static char *appendText(char *zIn, char const *zAppend, char quote){ |
1164 int len; | 1345 int len; |
1165 int i; | 1346 int i; |
1166 int nAppend = strlen30(zAppend); | 1347 int nAppend = strlen30(zAppend); |
1167 int nIn = (zIn?strlen30(zIn):0); | 1348 int nIn = (zIn?strlen30(zIn):0); |
1168 | 1349 |
1169 len = nAppend+nIn+1; | 1350 len = nAppend+nIn+1; |
1170 if( quote ){ | 1351 if( quote ){ |
(...skipping 26 matching lines...) Expand all Loading... |
1197 return zIn; | 1378 return zIn; |
1198 } | 1379 } |
1199 | 1380 |
1200 | 1381 |
1201 /* | 1382 /* |
1202 ** Execute a query statement that will generate SQL output. Print | 1383 ** Execute a query statement that will generate SQL output. Print |
1203 ** the result columns, comma-separated, on a line and then add a | 1384 ** the result columns, comma-separated, on a line and then add a |
1204 ** semicolon terminator to the end of that line. | 1385 ** semicolon terminator to the end of that line. |
1205 ** | 1386 ** |
1206 ** If the number of columns is 1 and that column contains text "--" | 1387 ** 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 | 1388 ** then write the semicolon on a separate line. That way, if a |
1208 ** "--" comment occurs at the end of the statement, the comment | 1389 ** "--" comment occurs at the end of the statement, the comment |
1209 ** won't consume the semicolon terminator. | 1390 ** won't consume the semicolon terminator. |
1210 */ | 1391 */ |
1211 static int run_table_dump_query( | 1392 static int run_table_dump_query( |
1212 ShellState *p, /* Query context */ | 1393 ShellState *p, /* Query context */ |
1213 const char *zSelect, /* SELECT statement to extract content */ | 1394 const char *zSelect, /* SELECT statement to extract content */ |
1214 const char *zFirstRow /* Print before first row, if not NULL */ | 1395 const char *zFirstRow /* Print before first row, if not NULL */ |
1215 ){ | 1396 ){ |
1216 sqlite3_stmt *pSelect; | 1397 sqlite3_stmt *pSelect; |
1217 int rc; | 1398 int rc; |
1218 int nResult; | 1399 int nResult; |
1219 int i; | 1400 int i; |
1220 const char *z; | 1401 const char *z; |
1221 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); | 1402 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); |
1222 if( rc!=SQLITE_OK || !pSelect ){ | 1403 if( rc!=SQLITE_OK || !pSelect ){ |
1223 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, | 1404 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, |
1224 sqlite3_errmsg(p->db)); | 1405 sqlite3_errmsg(p->db)); |
1225 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; | 1406 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; |
1226 return rc; | 1407 return rc; |
1227 } | 1408 } |
1228 rc = sqlite3_step(pSelect); | 1409 rc = sqlite3_step(pSelect); |
1229 nResult = sqlite3_column_count(pSelect); | 1410 nResult = sqlite3_column_count(pSelect); |
1230 while( rc==SQLITE_ROW ){ | 1411 while( rc==SQLITE_ROW ){ |
1231 if( zFirstRow ){ | 1412 if( zFirstRow ){ |
1232 utf8_printf(p->out, "%s", zFirstRow); | 1413 utf8_printf(p->out, "%s", zFirstRow); |
1233 zFirstRow = 0; | 1414 zFirstRow = 0; |
1234 } | 1415 } |
1235 z = (const char*)sqlite3_column_text(pSelect, 0); | 1416 z = (const char*)sqlite3_column_text(pSelect, 0); |
1236 utf8_printf(p->out, "%s", z); | 1417 utf8_printf(p->out, "%s", z); |
1237 for(i=1; i<nResult; i++){ | 1418 for(i=1; i<nResult; i++){ |
1238 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i)); | 1419 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i)); |
1239 } | 1420 } |
1240 if( z==0 ) z = ""; | 1421 if( z==0 ) z = ""; |
1241 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; | 1422 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; |
1242 if( z[0] ){ | 1423 if( z[0] ){ |
1243 raw_printf(p->out, "\n;\n"); | 1424 raw_printf(p->out, "\n;\n"); |
1244 }else{ | 1425 }else{ |
1245 raw_printf(p->out, ";\n"); | 1426 raw_printf(p->out, ";\n"); |
1246 } | 1427 } |
1247 rc = sqlite3_step(pSelect); | 1428 rc = sqlite3_step(pSelect); |
1248 } | 1429 } |
1249 rc = sqlite3_finalize(pSelect); | 1430 rc = sqlite3_finalize(pSelect); |
1250 if( rc!=SQLITE_OK ){ | 1431 if( rc!=SQLITE_OK ){ |
1251 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, | 1432 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, |
1252 sqlite3_errmsg(p->db)); | 1433 sqlite3_errmsg(p->db)); |
1253 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; | 1434 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; |
1254 } | 1435 } |
1255 return rc; | 1436 return rc; |
1256 } | 1437 } |
1257 | 1438 |
1258 /* | 1439 /* |
1259 ** Allocate space and save off current error string. | 1440 ** Allocate space and save off current error string. |
1260 */ | 1441 */ |
1261 static char *save_err_msg( | 1442 static char *save_err_msg( |
1262 sqlite3 *db /* Database to query */ | 1443 sqlite3 *db /* Database to query */ |
1263 ){ | 1444 ){ |
1264 int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); | 1445 int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); |
1265 char *zErrMsg = sqlite3_malloc64(nErrMsg); | 1446 char *zErrMsg = sqlite3_malloc64(nErrMsg); |
1266 if( zErrMsg ){ | 1447 if( zErrMsg ){ |
1267 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); | 1448 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); |
1268 } | 1449 } |
1269 return zErrMsg; | 1450 return zErrMsg; |
1270 } | 1451 } |
1271 | 1452 |
| 1453 #ifdef __linux__ |
| 1454 /* |
| 1455 ** Attempt to display I/O stats on Linux using /proc/PID/io |
| 1456 */ |
| 1457 static void displayLinuxIoStats(FILE *out){ |
| 1458 FILE *in; |
| 1459 char z[200]; |
| 1460 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); |
| 1461 in = fopen(z, "rb"); |
| 1462 if( in==0 ) return; |
| 1463 while( fgets(z, sizeof(z), in)!=0 ){ |
| 1464 static const struct { |
| 1465 const char *zPattern; |
| 1466 const char *zDesc; |
| 1467 } aTrans[] = { |
| 1468 { "rchar: ", "Bytes received by read():" }, |
| 1469 { "wchar: ", "Bytes sent to write():" }, |
| 1470 { "syscr: ", "Read() system calls:" }, |
| 1471 { "syscw: ", "Write() system calls:" }, |
| 1472 { "read_bytes: ", "Bytes read from storage:" }, |
| 1473 { "write_bytes: ", "Bytes written to storage:" }, |
| 1474 { "cancelled_write_bytes: ", "Cancelled write bytes:" }, |
| 1475 }; |
| 1476 int i; |
| 1477 for(i=0; i<ArraySize(aTrans); i++){ |
| 1478 int n = (int)strlen(aTrans[i].zPattern); |
| 1479 if( strncmp(aTrans[i].zPattern, z, n)==0 ){ |
| 1480 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]); |
| 1481 break; |
| 1482 } |
| 1483 } |
| 1484 } |
| 1485 fclose(in); |
| 1486 } |
| 1487 #endif |
| 1488 |
| 1489 |
1272 /* | 1490 /* |
1273 ** Display memory stats. | 1491 ** Display memory stats. |
1274 */ | 1492 */ |
1275 static int display_stats( | 1493 static int display_stats( |
1276 sqlite3 *db, /* Database to query */ | 1494 sqlite3 *db, /* Database to query */ |
1277 ShellState *pArg, /* Pointer to ShellState */ | 1495 ShellState *pArg, /* Pointer to ShellState */ |
1278 int bReset /* True to reset the stats */ | 1496 int bReset /* True to reset the stats */ |
1279 ){ | 1497 ){ |
1280 int iCur; | 1498 int iCur; |
1281 int iHiwtr; | 1499 int iHiwtr; |
1282 | 1500 |
1283 if( pArg && pArg->out ){ | 1501 if( pArg && pArg->out ){ |
1284 | 1502 |
1285 iHiwtr = iCur = -1; | 1503 iHiwtr = iCur = -1; |
1286 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); | 1504 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); |
1287 raw_printf(pArg->out, | 1505 raw_printf(pArg->out, |
1288 "Memory Used: %d (max %d) bytes\n", | 1506 "Memory Used: %d (max %d) bytes\n", |
1289 iCur, iHiwtr); | 1507 iCur, iHiwtr); |
1290 iHiwtr = iCur = -1; | 1508 iHiwtr = iCur = -1; |
1291 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); | 1509 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); |
1292 raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", | 1510 raw_printf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", |
1293 iCur, iHiwtr); | 1511 iCur, iHiwtr); |
1294 if( pArg->shellFlgs & SHFLG_Pagecache ){ | 1512 if( pArg->shellFlgs & SHFLG_Pagecache ){ |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 } | 1576 } |
1359 iHiwtr = iCur = -1; | 1577 iHiwtr = iCur = -1; |
1360 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); | 1578 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); |
1361 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", | 1579 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", |
1362 iCur); | 1580 iCur); |
1363 iHiwtr = iCur = -1; | 1581 iHiwtr = iCur = -1; |
1364 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); | 1582 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); |
1365 raw_printf(pArg->out, "Page cache hits: %d\n", iCur); | 1583 raw_printf(pArg->out, "Page cache hits: %d\n", iCur); |
1366 iHiwtr = iCur = -1; | 1584 iHiwtr = iCur = -1; |
1367 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); | 1585 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); |
1368 raw_printf(pArg->out, "Page cache misses: %d\n", iCur); | 1586 raw_printf(pArg->out, "Page cache misses: %d\n", iCur); |
1369 iHiwtr = iCur = -1; | 1587 iHiwtr = iCur = -1; |
1370 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); | 1588 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); |
1371 raw_printf(pArg->out, "Page cache writes: %d\n", iCur); | 1589 raw_printf(pArg->out, "Page cache writes: %d\n", iCur); |
1372 iHiwtr = iCur = -1; | 1590 iHiwtr = iCur = -1; |
1373 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); | 1591 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); |
1374 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", | 1592 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", |
1375 iCur); | 1593 iCur); |
1376 iHiwtr = iCur = -1; | 1594 iHiwtr = iCur = -1; |
1377 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); | 1595 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); |
1378 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", | 1596 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", |
1379 iCur); | 1597 iCur); |
1380 } | 1598 } |
1381 | 1599 |
1382 if( pArg && pArg->out && db && pArg->pStmt ){ | 1600 if( pArg && pArg->out && db && pArg->pStmt ){ |
1383 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, | 1601 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, |
1384 bReset); | 1602 bReset); |
1385 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); | 1603 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); |
1386 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); | 1604 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); |
1387 raw_printf(pArg->out, "Sort Operations: %d\n", iCur); | 1605 raw_printf(pArg->out, "Sort Operations: %d\n", iCur); |
1388 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); | 1606 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); |
1389 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); | 1607 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); |
1390 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); | 1608 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); |
1391 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); | 1609 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); |
1392 } | 1610 } |
1393 | 1611 |
| 1612 #ifdef __linux__ |
| 1613 displayLinuxIoStats(pArg->out); |
| 1614 #endif |
| 1615 |
1394 /* Do not remove this machine readable comment: extra-stats-output-here */ | 1616 /* Do not remove this machine readable comment: extra-stats-output-here */ |
1395 | 1617 |
1396 return 0; | 1618 return 0; |
1397 } | 1619 } |
1398 | 1620 |
1399 /* | 1621 /* |
1400 ** Display scan stats. | 1622 ** Display scan stats. |
1401 */ | 1623 */ |
1402 static void display_scanstats( | 1624 static void display_scanstats( |
1403 sqlite3 *db, /* Database to query */ | 1625 sqlite3 *db, /* Database to query */ |
(...skipping 23 matching lines...) Expand all Loading... |
1427 if( n==0 ){ | 1649 if( n==0 ){ |
1428 rEstLoop = (double)nLoop; | 1650 rEstLoop = (double)nLoop; |
1429 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k); | 1651 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k); |
1430 } | 1652 } |
1431 n++; | 1653 n++; |
1432 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); | 1654 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); |
1433 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); | 1655 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); |
1434 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); | 1656 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); |
1435 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); | 1657 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); |
1436 rEstLoop *= rEst; | 1658 rEstLoop *= rEst; |
1437 raw_printf(pArg->out, | 1659 raw_printf(pArg->out, |
1438 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", | 1660 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", |
1439 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst | 1661 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst |
1440 ); | 1662 ); |
1441 } | 1663 } |
1442 } | 1664 } |
1443 raw_printf(pArg->out, "---------------------------\n"); | 1665 raw_printf(pArg->out, "---------------------------\n"); |
1444 #endif | 1666 #endif |
1445 } | 1667 } |
1446 | 1668 |
1447 /* | 1669 /* |
1448 ** Parameter azArray points to a zero-terminated array of strings. zStr | 1670 ** Parameter azArray points to a zero-terminated array of strings. zStr |
1449 ** points to a single nul-terminated string. Return non-zero if zStr | 1671 ** 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. | 1672 ** is equal, according to strcmp(), to any of the strings in the array. |
1451 ** Otherwise, return zero. | 1673 ** Otherwise, return zero. |
1452 */ | 1674 */ |
1453 static int str_in_array(const char *zStr, const char **azArray){ | 1675 static int str_in_array(const char *zStr, const char **azArray){ |
1454 int i; | 1676 int i; |
1455 for(i=0; azArray[i]; i++){ | 1677 for(i=0; azArray[i]; i++){ |
1456 if( 0==strcmp(zStr, azArray[i]) ) return 1; | 1678 if( 0==strcmp(zStr, azArray[i]) ) return 1; |
1457 } | 1679 } |
1458 return 0; | 1680 return 0; |
1459 } | 1681 } |
1460 | 1682 |
1461 /* | 1683 /* |
1462 ** If compiled statement pSql appears to be an EXPLAIN statement, allocate | 1684 ** If compiled statement pSql appears to be an EXPLAIN statement, allocate |
1463 ** and populate the ShellState.aiIndent[] array with the number of | 1685 ** and populate the ShellState.aiIndent[] array with the number of |
1464 ** spaces each opcode should be indented before it is output. | 1686 ** spaces each opcode should be indented before it is output. |
1465 ** | 1687 ** |
1466 ** The indenting rules are: | 1688 ** The indenting rules are: |
1467 ** | 1689 ** |
1468 ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent | 1690 ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent |
1469 ** all opcodes that occur between the p2 jump destination and the opcode | 1691 ** all opcodes that occur between the p2 jump destination and the opcode |
1470 ** itself by 2 spaces. | 1692 ** itself by 2 spaces. |
1471 ** | 1693 ** |
1472 ** * For each "Goto", if the jump destination is earlier in the program | 1694 ** * For each "Goto", if the jump destination is earlier in the program |
1473 ** and ends on one of: | 1695 ** and ends on one of: |
1474 ** Yield SeekGt SeekLt RowSetRead Rewind | 1696 ** Yield SeekGt SeekLt RowSetRead Rewind |
1475 ** or if the P1 parameter is one instead of zero, | 1697 ** or if the P1 parameter is one instead of zero, |
1476 ** then indent all opcodes between the earlier instruction | 1698 ** then indent all opcodes between the earlier instruction |
1477 ** and "Goto" by 2 spaces. | 1699 ** and "Goto" by 2 spaces. |
1478 */ | 1700 */ |
1479 static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ | 1701 static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ |
1480 const char *zSql; /* The text of the SQL statement */ | 1702 const char *zSql; /* The text of the SQL statement */ |
1481 const char *z; /* Used to check if this is an EXPLAIN */ | 1703 const char *z; /* Used to check if this is an EXPLAIN */ |
1482 int *abYield = 0; /* True if op is an OP_Yield */ | 1704 int *abYield = 0; /* True if op is an OP_Yield */ |
1483 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ | 1705 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ |
1484 int iOp; /* Index of operation in p->aiIndent[] */ | 1706 int iOp; /* Index of operation in p->aiIndent[] */ |
1485 | 1707 |
1486 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", | 1708 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", |
1487 "NextIfOpen", "PrevIfOpen", 0 }; | 1709 "NextIfOpen", "PrevIfOpen", 0 }; |
1488 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", | 1710 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", |
1489 "Rewind", 0 }; | 1711 "Rewind", 0 }; |
1490 const char *azGoto[] = { "Goto", 0 }; | 1712 const char *azGoto[] = { "Goto", 0 }; |
1491 | 1713 |
1492 /* Try to figure out if this is really an EXPLAIN statement. If this | 1714 /* Try to figure out if this is really an EXPLAIN statement. If this |
1493 ** cannot be verified, return early. */ | 1715 ** cannot be verified, return early. */ |
| 1716 if( sqlite3_column_count(pSql)!=8 ){ |
| 1717 p->cMode = p->mode; |
| 1718 return; |
| 1719 } |
1494 zSql = sqlite3_sql(pSql); | 1720 zSql = sqlite3_sql(pSql); |
1495 if( zSql==0 ) return; | 1721 if( zSql==0 ) return; |
1496 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); | 1722 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); |
1497 if( sqlite3_strnicmp(z, "explain", 7) ) return; | 1723 if( sqlite3_strnicmp(z, "explain", 7) ){ |
| 1724 p->cMode = p->mode; |
| 1725 return; |
| 1726 } |
1498 | 1727 |
1499 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ | 1728 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ |
1500 int i; | 1729 int i; |
1501 int iAddr = sqlite3_column_int(pSql, 0); | 1730 int iAddr = sqlite3_column_int(pSql, 0); |
1502 const char *zOp = (const char*)sqlite3_column_text(pSql, 1); | 1731 const char *zOp = (const char*)sqlite3_column_text(pSql, 1); |
1503 | 1732 |
1504 /* Set p2 to the P2 field of the current opcode. Then, assuming that | 1733 /* 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 | 1734 ** 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 | 1735 ** 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 | 1736 ** the current instruction is part of a sub-program generated by an |
1508 ** SQL trigger or foreign key. */ | 1737 ** SQL trigger or foreign key. */ |
1509 int p2 = sqlite3_column_int(pSql, 3); | 1738 int p2 = sqlite3_column_int(pSql, 3); |
1510 int p2op = (p2 + (iOp-iAddr)); | 1739 int p2op = (p2 + (iOp-iAddr)); |
1511 | 1740 |
1512 /* Grow the p->aiIndent array as required */ | 1741 /* Grow the p->aiIndent array as required */ |
1513 if( iOp>=nAlloc ){ | 1742 if( iOp>=nAlloc ){ |
| 1743 if( iOp==0 ){ |
| 1744 /* Do further verfication that this is explain output. Abort if |
| 1745 ** it is not */ |
| 1746 static const char *explainCols[] = { |
| 1747 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; |
| 1748 int jj; |
| 1749 for(jj=0; jj<ArraySize(explainCols); jj++){ |
| 1750 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){ |
| 1751 p->cMode = p->mode; |
| 1752 sqlite3_reset(pSql); |
| 1753 return; |
| 1754 } |
| 1755 } |
| 1756 } |
1514 nAlloc += 100; | 1757 nAlloc += 100; |
1515 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); | 1758 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); |
1516 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); | 1759 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); |
1517 } | 1760 } |
1518 abYield[iOp] = str_in_array(zOp, azYield); | 1761 abYield[iOp] = str_in_array(zOp, azYield); |
1519 p->aiIndent[iOp] = 0; | 1762 p->aiIndent[iOp] = 0; |
1520 p->nIndent = iOp+1; | 1763 p->nIndent = iOp+1; |
1521 | 1764 |
1522 if( str_in_array(zOp, azNext) ){ | 1765 if( str_in_array(zOp, azNext) ){ |
1523 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; | 1766 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; |
1524 } | 1767 } |
1525 if( str_in_array(zOp, azGoto) && p2op<p->nIndent | 1768 if( str_in_array(zOp, azGoto) && p2op<p->nIndent |
1526 && (abYield[p2op] || sqlite3_column_int(pSql, 2)) | 1769 && (abYield[p2op] || sqlite3_column_int(pSql, 2)) |
1527 ){ | 1770 ){ |
1528 for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; | 1771 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; |
1529 } | 1772 } |
1530 } | 1773 } |
1531 | 1774 |
1532 p->iIndent = 0; | 1775 p->iIndent = 0; |
1533 sqlite3_free(abYield); | 1776 sqlite3_free(abYield); |
1534 sqlite3_reset(pSql); | 1777 sqlite3_reset(pSql); |
1535 } | 1778 } |
1536 | 1779 |
1537 /* | 1780 /* |
1538 ** Free the array allocated by explain_data_prepare(). | 1781 ** Free the array allocated by explain_data_prepare(). |
1539 */ | 1782 */ |
1540 static void explain_data_delete(ShellState *p){ | 1783 static void explain_data_delete(ShellState *p){ |
1541 sqlite3_free(p->aiIndent); | 1784 sqlite3_free(p->aiIndent); |
1542 p->aiIndent = 0; | 1785 p->aiIndent = 0; |
1543 p->nIndent = 0; | 1786 p->nIndent = 0; |
1544 p->iIndent = 0; | 1787 p->iIndent = 0; |
1545 } | 1788 } |
1546 | 1789 |
1547 /* | 1790 /* |
1548 ** Execute a statement or set of statements. Print | 1791 ** Disable and restore .wheretrace and .selecttrace settings. |
1549 ** any result rows/columns depending on the current mode | 1792 */ |
| 1793 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 1794 extern int sqlite3SelectTrace; |
| 1795 static int savedSelectTrace; |
| 1796 #endif |
| 1797 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) |
| 1798 extern int sqlite3WhereTrace; |
| 1799 static int savedWhereTrace; |
| 1800 #endif |
| 1801 static void disable_debug_trace_modes(void){ |
| 1802 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 1803 savedSelectTrace = sqlite3SelectTrace; |
| 1804 sqlite3SelectTrace = 0; |
| 1805 #endif |
| 1806 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) |
| 1807 savedWhereTrace = sqlite3WhereTrace; |
| 1808 sqlite3WhereTrace = 0; |
| 1809 #endif |
| 1810 } |
| 1811 static void restore_debug_trace_modes(void){ |
| 1812 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
| 1813 sqlite3SelectTrace = savedSelectTrace; |
| 1814 #endif |
| 1815 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) |
| 1816 sqlite3WhereTrace = savedWhereTrace; |
| 1817 #endif |
| 1818 } |
| 1819 |
| 1820 /* |
| 1821 ** Run a prepared statement |
| 1822 */ |
| 1823 static void exec_prepared_stmt( |
| 1824 ShellState *pArg, /* Pointer to ShellState */ |
| 1825 sqlite3_stmt *pStmt, /* Statment to run */ |
| 1826 int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */ |
| 1827 ){ |
| 1828 int rc; |
| 1829 |
| 1830 /* perform the first step. this will tell us if we |
| 1831 ** have a result set or not and how wide it is. |
| 1832 */ |
| 1833 rc = sqlite3_step(pStmt); |
| 1834 /* if we have a result set... */ |
| 1835 if( SQLITE_ROW == rc ){ |
| 1836 /* if we have a callback... */ |
| 1837 if( xCallback ){ |
| 1838 /* allocate space for col name ptr, value ptr, and type */ |
| 1839 int nCol = sqlite3_column_count(pStmt); |
| 1840 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); |
| 1841 if( !pData ){ |
| 1842 rc = SQLITE_NOMEM; |
| 1843 }else{ |
| 1844 char **azCols = (char **)pData; /* Names of result columns */ |
| 1845 char **azVals = &azCols[nCol]; /* Results */ |
| 1846 int *aiTypes = (int *)&azVals[nCol]; /* Result types */ |
| 1847 int i, x; |
| 1848 assert(sizeof(int) <= sizeof(char *)); |
| 1849 /* save off ptrs to column names */ |
| 1850 for(i=0; i<nCol; i++){ |
| 1851 azCols[i] = (char *)sqlite3_column_name(pStmt, i); |
| 1852 } |
| 1853 do{ |
| 1854 /* extract the data and data types */ |
| 1855 for(i=0; i<nCol; i++){ |
| 1856 aiTypes[i] = x = sqlite3_column_type(pStmt, i); |
| 1857 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ |
| 1858 azVals[i] = ""; |
| 1859 }else{ |
| 1860 azVals[i] = (char*)sqlite3_column_text(pStmt, i); |
| 1861 } |
| 1862 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ |
| 1863 rc = SQLITE_NOMEM; |
| 1864 break; /* from for */ |
| 1865 } |
| 1866 } /* end for */ |
| 1867 |
| 1868 /* if data and types extracted successfully... */ |
| 1869 if( SQLITE_ROW == rc ){ |
| 1870 /* call the supplied callback with the result row data */ |
| 1871 if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){ |
| 1872 rc = SQLITE_ABORT; |
| 1873 }else{ |
| 1874 rc = sqlite3_step(pStmt); |
| 1875 } |
| 1876 } |
| 1877 } while( SQLITE_ROW == rc ); |
| 1878 sqlite3_free(pData); |
| 1879 } |
| 1880 }else{ |
| 1881 do{ |
| 1882 rc = sqlite3_step(pStmt); |
| 1883 } while( rc == SQLITE_ROW ); |
| 1884 } |
| 1885 } |
| 1886 } |
| 1887 |
| 1888 /* |
| 1889 ** Execute a statement or set of statements. Print |
| 1890 ** any result rows/columns depending on the current mode |
1550 ** set via the supplied callback. | 1891 ** set via the supplied callback. |
1551 ** | 1892 ** |
1552 ** This is very similar to SQLite's built-in sqlite3_exec() | 1893 ** This is very similar to SQLite's built-in sqlite3_exec() |
1553 ** function except it takes a slightly different callback | 1894 ** function except it takes a slightly different callback |
1554 ** and callback data argument. | 1895 ** and callback data argument. |
1555 */ | 1896 */ |
1556 static int shell_exec( | 1897 static int shell_exec( |
1557 sqlite3 *db, /* An open database */ | 1898 sqlite3 *db, /* An open database */ |
1558 const char *zSql, /* SQL to be evaluated */ | 1899 const char *zSql, /* SQL to be evaluated */ |
1559 int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ | 1900 int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ |
1560 /* (not the same as sqlite3_exec) */ | 1901 /* (not the same as sqlite3_exec) */ |
1561 ShellState *pArg, /* Pointer to ShellState */ | 1902 ShellState *pArg, /* Pointer to ShellState */ |
1562 char **pzErrMsg /* Error msg written here */ | 1903 char **pzErrMsg /* Error msg written here */ |
1563 ){ | 1904 ){ |
1564 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ | 1905 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ |
1565 int rc = SQLITE_OK; /* Return Code */ | 1906 int rc = SQLITE_OK; /* Return Code */ |
1566 int rc2; | 1907 int rc2; |
1567 const char *zLeftover; /* Tail of unprocessed SQL */ | 1908 const char *zLeftover; /* Tail of unprocessed SQL */ |
1568 | 1909 |
1569 if( pzErrMsg ){ | 1910 if( pzErrMsg ){ |
1570 *pzErrMsg = NULL; | 1911 *pzErrMsg = NULL; |
1571 } | 1912 } |
1572 | 1913 |
1573 while( zSql[0] && (SQLITE_OK == rc) ){ | 1914 while( zSql[0] && (SQLITE_OK == rc) ){ |
| 1915 static const char *zStmtSql; |
1574 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); | 1916 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); |
1575 if( SQLITE_OK != rc ){ | 1917 if( SQLITE_OK != rc ){ |
1576 if( pzErrMsg ){ | 1918 if( pzErrMsg ){ |
1577 *pzErrMsg = save_err_msg(db); | 1919 *pzErrMsg = save_err_msg(db); |
1578 } | 1920 } |
1579 }else{ | 1921 }else{ |
1580 if( !pStmt ){ | 1922 if( !pStmt ){ |
1581 /* this happens for a comment or white-space */ | 1923 /* this happens for a comment or white-space */ |
1582 zSql = zLeftover; | 1924 zSql = zLeftover; |
1583 while( IsSpace(zSql[0]) ) zSql++; | 1925 while( IsSpace(zSql[0]) ) zSql++; |
1584 continue; | 1926 continue; |
1585 } | 1927 } |
| 1928 zStmtSql = sqlite3_sql(pStmt); |
| 1929 if( zStmtSql==0 ) zStmtSql = ""; |
| 1930 while( IsSpace(zStmtSql[0]) ) zStmtSql++; |
1586 | 1931 |
1587 /* save off the prepared statment handle and reset row count */ | 1932 /* save off the prepared statment handle and reset row count */ |
1588 if( pArg ){ | 1933 if( pArg ){ |
1589 pArg->pStmt = pStmt; | 1934 pArg->pStmt = pStmt; |
1590 pArg->cnt = 0; | 1935 pArg->cnt = 0; |
1591 } | 1936 } |
1592 | 1937 |
1593 /* echo the sql statement if echo on */ | 1938 /* echo the sql statement if echo on */ |
1594 if( pArg && pArg->echoOn ){ | 1939 if( pArg && pArg->echoOn ){ |
1595 const char *zStmtSql = sqlite3_sql(pStmt); | |
1596 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); | 1940 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); |
1597 } | 1941 } |
1598 | 1942 |
1599 /* Show the EXPLAIN QUERY PLAN if .eqp is on */ | 1943 /* Show the EXPLAIN QUERY PLAN if .eqp is on */ |
1600 if( pArg && pArg->autoEQP ){ | 1944 if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){ |
1601 sqlite3_stmt *pExplain; | 1945 sqlite3_stmt *pExplain; |
1602 char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", | 1946 char *zEQP; |
1603 sqlite3_sql(pStmt)); | 1947 disable_debug_trace_modes(); |
| 1948 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); |
1604 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); | 1949 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); |
1605 if( rc==SQLITE_OK ){ | 1950 if( rc==SQLITE_OK ){ |
1606 while( sqlite3_step(pExplain)==SQLITE_ROW ){ | 1951 while( sqlite3_step(pExplain)==SQLITE_ROW ){ |
1607 raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0)); | 1952 raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0)); |
1608 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); | 1953 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); |
1609 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); | 1954 raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); |
1610 utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); | 1955 utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); |
1611 } | 1956 } |
1612 } | 1957 } |
1613 sqlite3_finalize(pExplain); | 1958 sqlite3_finalize(pExplain); |
1614 sqlite3_free(zEQP); | 1959 sqlite3_free(zEQP); |
| 1960 if( pArg->autoEQP>=2 ){ |
| 1961 /* Also do an EXPLAIN for ".eqp full" mode */ |
| 1962 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); |
| 1963 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); |
| 1964 if( rc==SQLITE_OK ){ |
| 1965 pArg->cMode = MODE_Explain; |
| 1966 explain_data_prepare(pArg, pExplain); |
| 1967 exec_prepared_stmt(pArg, pExplain, xCallback); |
| 1968 explain_data_delete(pArg); |
| 1969 } |
| 1970 sqlite3_finalize(pExplain); |
| 1971 sqlite3_free(zEQP); |
| 1972 } |
| 1973 restore_debug_trace_modes(); |
1615 } | 1974 } |
1616 | 1975 |
1617 /* If the shell is currently in ".explain" mode, gather the extra | 1976 if( pArg ){ |
1618 ** data required to add indents to the output.*/ | 1977 pArg->cMode = pArg->mode; |
1619 if( pArg && pArg->mode==MODE_Explain ){ | 1978 if( pArg->autoExplain |
1620 explain_data_prepare(pArg, pStmt); | 1979 && sqlite3_column_count(pStmt)==8 |
1621 } | 1980 && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0 |
| 1981 ){ |
| 1982 pArg->cMode = MODE_Explain; |
| 1983 } |
1622 | 1984 |
1623 /* perform the first step. this will tell us if we | 1985 /* If the shell is currently in ".explain" mode, gather the extra |
1624 ** have a result set or not and how wide it is. | 1986 ** data required to add indents to the output.*/ |
1625 */ | 1987 if( pArg->cMode==MODE_Explain ){ |
1626 rc = sqlite3_step(pStmt); | 1988 explain_data_prepare(pArg, 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 } | 1989 } |
1678 } | 1990 } |
1679 | 1991 |
| 1992 exec_prepared_stmt(pArg, pStmt, xCallback); |
1680 explain_data_delete(pArg); | 1993 explain_data_delete(pArg); |
1681 | 1994 |
1682 /* print usage stats if stats on */ | 1995 /* print usage stats if stats on */ |
1683 if( pArg && pArg->statsOn ){ | 1996 if( pArg && pArg->statsOn ){ |
1684 display_stats(db, pArg, 0); | 1997 display_stats(db, pArg, 0); |
1685 } | 1998 } |
1686 | 1999 |
1687 /* print loop-counters if required */ | 2000 /* print loop-counters if required */ |
1688 if( pArg && pArg->scanstatsOn ){ | 2001 if( pArg && pArg->scanstatsOn ){ |
1689 display_scanstats(db, pArg); | 2002 display_scanstats(db, pArg); |
1690 } | 2003 } |
1691 | 2004 |
1692 /* Finalize the statement just executed. If this fails, save a | 2005 /* Finalize the statement just executed. If this fails, save a |
1693 ** copy of the error message. Otherwise, set zSql to point to the | 2006 ** copy of the error message. Otherwise, set zSql to point to the |
1694 ** next statement to execute. */ | 2007 ** next statement to execute. */ |
1695 rc2 = sqlite3_finalize(pStmt); | 2008 rc2 = sqlite3_finalize(pStmt); |
1696 if( rc!=SQLITE_NOMEM ) rc = rc2; | 2009 if( rc!=SQLITE_NOMEM ) rc = rc2; |
1697 if( rc==SQLITE_OK ){ | 2010 if( rc==SQLITE_OK ){ |
1698 zSql = zLeftover; | 2011 zSql = zLeftover; |
1699 while( IsSpace(zSql[0]) ) zSql++; | 2012 while( IsSpace(zSql[0]) ) zSql++; |
1700 }else if( pzErrMsg ){ | 2013 }else if( pzErrMsg ){ |
1701 *pzErrMsg = save_err_msg(db); | 2014 *pzErrMsg = save_err_msg(db); |
1702 } | 2015 } |
(...skipping 21 matching lines...) Expand all Loading... |
1724 const char *zType; | 2037 const char *zType; |
1725 const char *zSql; | 2038 const char *zSql; |
1726 const char *zPrepStmt = 0; | 2039 const char *zPrepStmt = 0; |
1727 ShellState *p = (ShellState *)pArg; | 2040 ShellState *p = (ShellState *)pArg; |
1728 | 2041 |
1729 UNUSED_PARAMETER(azCol); | 2042 UNUSED_PARAMETER(azCol); |
1730 if( nArg!=3 ) return 1; | 2043 if( nArg!=3 ) return 1; |
1731 zTable = azArg[0]; | 2044 zTable = azArg[0]; |
1732 zType = azArg[1]; | 2045 zType = azArg[1]; |
1733 zSql = azArg[2]; | 2046 zSql = azArg[2]; |
1734 | 2047 |
1735 if( strcmp(zTable, "sqlite_sequence")==0 ){ | 2048 if( strcmp(zTable, "sqlite_sequence")==0 ){ |
1736 zPrepStmt = "DELETE FROM sqlite_sequence;\n"; | 2049 zPrepStmt = "DELETE FROM sqlite_sequence;\n"; |
1737 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ | 2050 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ |
1738 raw_printf(p->out, "ANALYZE sqlite_master;\n"); | 2051 raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
1739 }else if( strncmp(zTable, "sqlite_", 7)==0 ){ | 2052 }else if( strncmp(zTable, "sqlite_", 7)==0 ){ |
1740 return 0; | 2053 return 0; |
1741 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ | 2054 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ |
1742 char *zIns; | 2055 char *zIns; |
1743 if( !p->writableSchema ){ | 2056 if( !p->writableSchema ){ |
1744 raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); | 2057 raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); |
1745 p->writableSchema = 1; | 2058 p->writableSchema = 1; |
1746 } | 2059 } |
1747 zIns = sqlite3_mprintf( | 2060 zIns = sqlite3_mprintf( |
1748 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" | 2061 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" |
1749 "VALUES('table','%q','%q',0,'%q');", | 2062 "VALUES('table','%q','%q',0,'%q');", |
1750 zTable, zTable, zSql); | 2063 zTable, zTable, zSql); |
1751 utf8_printf(p->out, "%s\n", zIns); | 2064 utf8_printf(p->out, "%s\n", zIns); |
1752 sqlite3_free(zIns); | 2065 sqlite3_free(zIns); |
1753 return 0; | 2066 return 0; |
1754 }else{ | 2067 }else{ |
1755 utf8_printf(p->out, "%s;\n", zSql); | 2068 printSchemaLine(p->out, zSql, ";\n"); |
1756 } | 2069 } |
1757 | 2070 |
1758 if( strcmp(zType, "table")==0 ){ | 2071 if( strcmp(zType, "table")==0 ){ |
1759 sqlite3_stmt *pTableInfo = 0; | 2072 sqlite3_stmt *pTableInfo = 0; |
1760 char *zSelect = 0; | 2073 char *zSelect = 0; |
1761 char *zTableInfo = 0; | 2074 char *zTableInfo = 0; |
1762 char *zTmp = 0; | 2075 char *zTmp = 0; |
1763 int nRow = 0; | 2076 int nRow = 0; |
1764 | 2077 |
1765 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); | 2078 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); |
1766 zTableInfo = appendText(zTableInfo, zTable, '"'); | 2079 zTableInfo = appendText(zTableInfo, zTable, '"'); |
1767 zTableInfo = appendText(zTableInfo, ");", 0); | 2080 zTableInfo = appendText(zTableInfo, ");", 0); |
1768 | 2081 |
1769 rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); | 2082 rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); |
1770 free(zTableInfo); | 2083 free(zTableInfo); |
1771 if( rc!=SQLITE_OK || !pTableInfo ){ | 2084 if( rc!=SQLITE_OK || !pTableInfo ){ |
1772 return 1; | 2085 return 1; |
1773 } | 2086 } |
1774 | 2087 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 } | 2126 } |
1814 | 2127 |
1815 /* | 2128 /* |
1816 ** Run zQuery. Use dump_callback() as the callback routine so that | 2129 ** Run zQuery. Use dump_callback() as the callback routine so that |
1817 ** the contents of the query are output as SQL statements. | 2130 ** the contents of the query are output as SQL statements. |
1818 ** | 2131 ** |
1819 ** If we get a SQLITE_CORRUPT error, rerun the query after appending | 2132 ** If we get a SQLITE_CORRUPT error, rerun the query after appending |
1820 ** "ORDER BY rowid DESC" to the end. | 2133 ** "ORDER BY rowid DESC" to the end. |
1821 */ | 2134 */ |
1822 static int run_schema_dump_query( | 2135 static int run_schema_dump_query( |
1823 ShellState *p, | 2136 ShellState *p, |
1824 const char *zQuery | 2137 const char *zQuery |
1825 ){ | 2138 ){ |
1826 int rc; | 2139 int rc; |
1827 char *zErr = 0; | 2140 char *zErr = 0; |
1828 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); | 2141 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); |
1829 if( rc==SQLITE_CORRUPT ){ | 2142 if( rc==SQLITE_CORRUPT ){ |
1830 char *zQ2; | 2143 char *zQ2; |
1831 int len = strlen30(zQuery); | 2144 int len = strlen30(zQuery); |
1832 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); | 2145 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); |
1833 if( zErr ){ | 2146 if( zErr ){ |
(...skipping 13 matching lines...) Expand all Loading... |
1847 sqlite3_free(zErr); | 2160 sqlite3_free(zErr); |
1848 free(zQ2); | 2161 free(zQ2); |
1849 } | 2162 } |
1850 return rc; | 2163 return rc; |
1851 } | 2164 } |
1852 | 2165 |
1853 /* | 2166 /* |
1854 ** Text of a help message | 2167 ** Text of a help message |
1855 */ | 2168 */ |
1856 static char zHelp[] = | 2169 static char zHelp[] = |
| 2170 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 2171 ".auth ON|OFF Show authorizer callbacks\n" |
| 2172 #endif |
1857 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" | 2173 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" |
1858 ".bail on|off Stop after hitting an error. Default OFF\n" | 2174 ".bail on|off Stop after hitting an error. Default OFF\n" |
1859 ".binary on|off Turn binary output on or off. Default OFF\n" | 2175 ".binary on|off Turn binary output on or off. Default OFF\n" |
1860 ".changes on|off Show number of rows changed by SQL\n" | 2176 ".changes on|off Show number of rows changed by SQL\n" |
| 2177 ".check GLOB Fail if output since .testcase does not match\n" |
1861 ".clone NEWDB Clone data into NEWDB from the existing database\n" | 2178 ".clone NEWDB Clone data into NEWDB from the existing database\n" |
1862 ".databases List names and files of attached databases\n" | 2179 ".databases List names and files of attached databases\n" |
1863 ".dbinfo ?DB? Show status information about the database\n" | 2180 ".dbinfo ?DB? Show status information about the database\n" |
1864 ".dump ?TABLE? ... Dump the database in an SQL text format\n" | 2181 ".dump ?TABLE? ... Dump the database in an SQL text format\n" |
1865 " If TABLE specified, only dump tables matching\n" | 2182 " If TABLE specified, only dump tables matching\n" |
1866 " LIKE pattern TABLE.\n" | 2183 " LIKE pattern TABLE.\n" |
1867 ".echo on|off Turn command echo on or off\n" | 2184 ".echo on|off Turn command echo on or off\n" |
1868 ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n" | 2185 ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" |
1869 ".exit Exit this program\n" | 2186 ".exit Exit this program\n" |
1870 ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n" | 2187 ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n" |
1871 " With no args, it turns EXPLAIN on.\n" | 2188 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\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" | 2189 ".headers on|off Turn display of headers on or off\n" |
1874 ".help Show this message\n" | 2190 ".help Show this message\n" |
1875 ".import FILE TABLE Import data from FILE into TABLE\n" | 2191 ".import FILE TABLE Import data from FILE into TABLE\n" |
| 2192 #ifndef SQLITE_OMIT_TEST_CONTROL |
| 2193 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" |
| 2194 #endif |
1876 ".indexes ?TABLE? Show names of all indexes\n" | 2195 ".indexes ?TABLE? Show names of all indexes\n" |
1877 " If TABLE specified, only show indexes for tables\n" | 2196 " If TABLE specified, only show indexes for tables\n" |
1878 " matching LIKE pattern TABLE.\n" | 2197 " matching LIKE pattern TABLE.\n" |
1879 #ifdef SQLITE_ENABLE_IOTRACE | 2198 #ifdef SQLITE_ENABLE_IOTRACE |
1880 ".iotrace FILE Enable I/O diagnostic logging to FILE\n" | 2199 ".iotrace FILE Enable I/O diagnostic logging to FILE\n" |
1881 #endif | 2200 #endif |
1882 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" | 2201 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" |
| 2202 ".lint OPTIONS Report potential schema issues. Options:\n" |
| 2203 " fkey-indexes Find missing foreign key indexes\n" |
1883 #ifndef SQLITE_OMIT_LOAD_EXTENSION | 2204 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
1884 ".load FILE ?ENTRY? Load an extension library\n" | 2205 ".load FILE ?ENTRY? Load an extension library\n" |
1885 #endif | 2206 #endif |
1886 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" | 2207 ".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" | 2208 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" |
1888 " ascii Columns/rows delimited by 0x1F and 0x1E\n" | 2209 " ascii Columns/rows delimited by 0x1F and 0x1E\n" |
1889 " csv Comma-separated values\n" | 2210 " csv Comma-separated values\n" |
1890 " column Left-aligned columns. (See .width)\n" | 2211 " column Left-aligned columns. (See .width)\n" |
1891 " html HTML <table> code\n" | 2212 " html HTML <table> code\n" |
1892 " insert SQL insert statements for TABLE\n" | 2213 " insert SQL insert statements for TABLE\n" |
1893 " line One value per line\n" | 2214 " line One value per line\n" |
1894 " list Values delimited by .separator strings\n" | 2215 " list Values delimited by .separator strings\n" |
| 2216 " quote Escape answers as for SQL\n" |
1895 " tabs Tab-separated values\n" | 2217 " tabs Tab-separated values\n" |
1896 " tcl TCL list elements\n" | 2218 " tcl TCL list elements\n" |
1897 ".nullvalue STRING Use STRING in place of NULL values\n" | 2219 ".nullvalue STRING Use STRING in place of NULL values\n" |
1898 ".once FILENAME Output for the next SQL command only to FILENAME\n" | 2220 ".once FILENAME Output for the next SQL command only to FILENAME\n" |
1899 ".open ?FILENAME? Close existing database and reopen FILENAME\n" | 2221 ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| 2222 " The --new starts with an empty file\n" |
1900 ".output ?FILENAME? Send output to FILENAME or stdout\n" | 2223 ".output ?FILENAME? Send output to FILENAME or stdout\n" |
1901 ".print STRING... Print literal STRING\n" | 2224 ".print STRING... Print literal STRING\n" |
1902 ".prompt MAIN CONTINUE Replace the standard prompts\n" | 2225 ".prompt MAIN CONTINUE Replace the standard prompts\n" |
1903 ".quit Exit this program\n" | 2226 ".quit Exit this program\n" |
1904 ".read FILENAME Execute SQL in FILENAME\n" | 2227 ".read FILENAME Execute SQL in FILENAME\n" |
1905 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" | 2228 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" |
1906 ".save FILE Write in-memory database into FILE\n" | 2229 ".save FILE Write in-memory database into FILE\n" |
1907 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" | 2230 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" |
1908 ".schema ?TABLE? Show the CREATE statements\n" | 2231 ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" |
1909 " If TABLE specified, only show tables matching\n" | 2232 " Add --indent for pretty-printing\n" |
1910 " LIKE pattern TABLE.\n" | |
1911 ".separator COL ?ROW? Change the column separator and optionally the row\n" | 2233 ".separator COL ?ROW? Change the column separator and optionally the row\n" |
1912 " separator for both the output mode and .import\n" | 2234 " separator for both the output mode and .import\n" |
| 2235 #if defined(SQLITE_ENABLE_SESSION) |
| 2236 ".session CMD ... Create or control sessions\n" |
| 2237 #endif |
1913 ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" | 2238 ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" |
1914 ".show Show the current values for various settings\n" | 2239 ".show Show the current values for various settings\n" |
1915 ".stats on|off Turn stats on or off\n" | 2240 ".stats ?on|off? Show stats or turn stats on or off\n" |
1916 ".system CMD ARGS... Run CMD ARGS... in a system shell\n" | 2241 ".system CMD ARGS... Run CMD ARGS... in a system shell\n" |
1917 ".tables ?TABLE? List names of tables\n" | 2242 ".tables ?TABLE? List names of tables\n" |
1918 " If TABLE specified, only list tables matching\n" | 2243 " If TABLE specified, only list tables matching\n" |
1919 " LIKE pattern TABLE.\n" | 2244 " LIKE pattern TABLE.\n" |
| 2245 ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" |
1920 ".timeout MS Try opening locked tables for MS milliseconds\n" | 2246 ".timeout MS Try opening locked tables for MS milliseconds\n" |
1921 ".timer on|off Turn SQL timer on or off\n" | 2247 ".timer on|off Turn SQL timer on or off\n" |
1922 ".trace FILE|off Output each SQL statement as it is run\n" | 2248 ".trace FILE|off Output each SQL statement as it is run\n" |
1923 ".vfsinfo ?AUX? Information about the top-level VFS\n" | 2249 ".vfsinfo ?AUX? Information about the top-level VFS\n" |
| 2250 ".vfslist List all available VFSes\n" |
1924 ".vfsname ?AUX? Print the name of the VFS stack\n" | 2251 ".vfsname ?AUX? Print the name of the VFS stack\n" |
1925 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" | 2252 ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" |
1926 " Negative values right-justify\n" | 2253 " Negative values right-justify\n" |
1927 ; | 2254 ; |
1928 | 2255 |
| 2256 #if defined(SQLITE_ENABLE_SESSION) |
| 2257 /* |
| 2258 ** Print help information for the ".sessions" command |
| 2259 */ |
| 2260 void session_help(ShellState *p){ |
| 2261 raw_printf(p->out, |
| 2262 ".session ?NAME? SUBCOMMAND ?ARGS...?\n" |
| 2263 "If ?NAME? is omitted, the first defined session is used.\n" |
| 2264 "Subcommands:\n" |
| 2265 " attach TABLE Attach TABLE\n" |
| 2266 " changeset FILE Write a changeset into FILE\n" |
| 2267 " close Close one session\n" |
| 2268 " enable ?BOOLEAN? Set or query the enable bit\n" |
| 2269 " filter GLOB... Reject tables matching GLOBs\n" |
| 2270 " indirect ?BOOLEAN? Mark or query the indirect status\n" |
| 2271 " isempty Query whether the session is empty\n" |
| 2272 " list List currently open session names\n" |
| 2273 " open DB NAME Open a new session on DB\n" |
| 2274 " patchset FILE Write a patchset into FILE\n" |
| 2275 ); |
| 2276 } |
| 2277 #endif |
| 2278 |
| 2279 |
1929 /* Forward reference */ | 2280 /* Forward reference */ |
1930 static int process_input(ShellState *p, FILE *in); | 2281 static int process_input(ShellState *p, FILE *in); |
| 2282 |
| 2283 /* |
| 2284 ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 2285 ** and return a pointer to the buffer. The caller is responsible for freeing |
| 2286 ** the memory. |
| 2287 ** |
| 2288 ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes |
| 2289 ** read. |
| 2290 ** |
| 2291 ** For convenience, a nul-terminator byte is always appended to the data read |
| 2292 ** from the file before the buffer is returned. This byte is not included in |
| 2293 ** the final value of (*pnByte), if applicable. |
| 2294 ** |
| 2295 ** NULL is returned if any error is encountered. The final value of *pnByte |
| 2296 ** is undefined in this case. |
| 2297 */ |
| 2298 static char *readFile(const char *zName, int *pnByte){ |
| 2299 FILE *in = fopen(zName, "rb"); |
| 2300 long nIn; |
| 2301 size_t nRead; |
| 2302 char *pBuf; |
| 2303 if( in==0 ) return 0; |
| 2304 fseek(in, 0, SEEK_END); |
| 2305 nIn = ftell(in); |
| 2306 rewind(in); |
| 2307 pBuf = sqlite3_malloc64( nIn+1 ); |
| 2308 if( pBuf==0 ) return 0; |
| 2309 nRead = fread(pBuf, nIn, 1, in); |
| 2310 fclose(in); |
| 2311 if( nRead!=1 ){ |
| 2312 sqlite3_free(pBuf); |
| 2313 return 0; |
| 2314 } |
| 2315 pBuf[nIn] = 0; |
| 2316 if( pnByte ) *pnByte = nIn; |
| 2317 return pBuf; |
| 2318 } |
| 2319 |
1931 /* | 2320 /* |
1932 ** Implementation of the "readfile(X)" SQL function. The entire content | 2321 ** 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 | 2322 ** 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. | 2323 ** if the file does not exist or is unreadable. |
1935 */ | 2324 */ |
1936 static void readfileFunc( | 2325 static void readfileFunc( |
1937 sqlite3_context *context, | 2326 sqlite3_context *context, |
1938 int argc, | 2327 int argc, |
1939 sqlite3_value **argv | 2328 sqlite3_value **argv |
1940 ){ | 2329 ){ |
1941 const char *zName; | 2330 const char *zName; |
1942 FILE *in; | |
1943 long nIn; | |
1944 void *pBuf; | 2331 void *pBuf; |
| 2332 int nBuf; |
1945 | 2333 |
1946 UNUSED_PARAMETER(argc); | 2334 UNUSED_PARAMETER(argc); |
1947 zName = (const char*)sqlite3_value_text(argv[0]); | 2335 zName = (const char*)sqlite3_value_text(argv[0]); |
1948 if( zName==0 ) return; | 2336 if( zName==0 ) return; |
1949 in = fopen(zName, "rb"); | 2337 pBuf = readFile(zName, &nBuf); |
1950 if( in==0 ) return; | 2338 if( pBuf ) sqlite3_result_blob(context, pBuf, nBuf, sqlite3_free); |
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 } | 2339 } |
1962 | 2340 |
1963 /* | 2341 /* |
1964 ** Implementation of the "writefile(X,Y)" SQL function. The argument Y | 2342 ** 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 | 2343 ** 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 | 2344 ** NULL is returned if something goes wrong, such as being unable to open |
1967 ** file X for writing. | 2345 ** file X for writing. |
1968 */ | 2346 */ |
1969 static void writefileFunc( | 2347 static void writefileFunc( |
1970 sqlite3_context *context, | 2348 sqlite3_context *context, |
(...skipping 13 matching lines...) Expand all Loading... |
1984 z = (const char*)sqlite3_value_blob(argv[1]); | 2362 z = (const char*)sqlite3_value_blob(argv[1]); |
1985 if( z==0 ){ | 2363 if( z==0 ){ |
1986 rc = 0; | 2364 rc = 0; |
1987 }else{ | 2365 }else{ |
1988 rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); | 2366 rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); |
1989 } | 2367 } |
1990 fclose(out); | 2368 fclose(out); |
1991 sqlite3_result_int64(context, rc); | 2369 sqlite3_result_int64(context, rc); |
1992 } | 2370 } |
1993 | 2371 |
| 2372 #if defined(SQLITE_ENABLE_SESSION) |
| 2373 /* |
| 2374 ** Close a single OpenSession object and release all of its associated |
| 2375 ** resources. |
| 2376 */ |
| 2377 static void session_close(OpenSession *pSession){ |
| 2378 int i; |
| 2379 sqlite3session_delete(pSession->p); |
| 2380 sqlite3_free(pSession->zName); |
| 2381 for(i=0; i<pSession->nFilter; i++){ |
| 2382 sqlite3_free(pSession->azFilter[i]); |
| 2383 } |
| 2384 sqlite3_free(pSession->azFilter); |
| 2385 memset(pSession, 0, sizeof(OpenSession)); |
| 2386 } |
| 2387 #endif |
| 2388 |
| 2389 /* |
| 2390 ** Close all OpenSession objects and release all associated resources. |
| 2391 */ |
| 2392 #if defined(SQLITE_ENABLE_SESSION) |
| 2393 static void session_close_all(ShellState *p){ |
| 2394 int i; |
| 2395 for(i=0; i<p->nSession; i++){ |
| 2396 session_close(&p->aSession[i]); |
| 2397 } |
| 2398 p->nSession = 0; |
| 2399 } |
| 2400 #else |
| 2401 # define session_close_all(X) |
| 2402 #endif |
| 2403 |
| 2404 /* |
| 2405 ** Implementation of the xFilter function for an open session. Omit |
| 2406 ** any tables named by ".session filter" but let all other table through. |
| 2407 */ |
| 2408 #if defined(SQLITE_ENABLE_SESSION) |
| 2409 static int session_filter(void *pCtx, const char *zTab){ |
| 2410 OpenSession *pSession = (OpenSession*)pCtx; |
| 2411 int i; |
| 2412 for(i=0; i<pSession->nFilter; i++){ |
| 2413 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; |
| 2414 } |
| 2415 return 1; |
| 2416 } |
| 2417 #endif |
| 2418 |
1994 /* | 2419 /* |
1995 ** Make sure the database is open. If it is not, then open it. If | 2420 ** 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. | 2421 ** the database fails to open, print an error message and exit. |
1997 */ | 2422 */ |
1998 static void open_db(ShellState *p, int keepAlive){ | 2423 static void open_db(ShellState *p, int keepAlive){ |
1999 if( p->db==0 ){ | 2424 if( p->db==0 ){ |
2000 sqlite3_initialize(); | 2425 sqlite3_initialize(); |
2001 sqlite3_open(p->zDbFilename, &p->db); | 2426 sqlite3_open(p->zDbFilename, &p->db); |
2002 globalDb = p->db; | 2427 globalDb = p->db; |
2003 if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ | 2428 if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ |
2004 sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, | 2429 sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, |
2005 shellstaticFunc, 0, 0); | 2430 shellstaticFunc, 0, 0); |
2006 } | 2431 } |
2007 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ | 2432 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ |
2008 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", | 2433 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", |
2009 p->zDbFilename, sqlite3_errmsg(p->db)); | 2434 p->zDbFilename, sqlite3_errmsg(p->db)); |
2010 if( keepAlive ) return; | 2435 if( keepAlive ) return; |
2011 exit(1); | 2436 exit(1); |
2012 } | 2437 } |
2013 #ifndef SQLITE_OMIT_LOAD_EXTENSION | 2438 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
2014 sqlite3_enable_load_extension(p->db, 1); | 2439 sqlite3_enable_load_extension(p->db, 1); |
2015 #endif | 2440 #endif |
2016 sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, | 2441 sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, |
2017 readfileFunc, 0, 0); | 2442 readfileFunc, 0, 0); |
2018 sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, | 2443 sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2162 | 2587 |
2163 /* | 2588 /* |
2164 ** Close an output file, assuming it is not stderr or stdout | 2589 ** Close an output file, assuming it is not stderr or stdout |
2165 */ | 2590 */ |
2166 static void output_file_close(FILE *f){ | 2591 static void output_file_close(FILE *f){ |
2167 if( f && f!=stdout && f!=stderr ) fclose(f); | 2592 if( f && f!=stdout && f!=stderr ) fclose(f); |
2168 } | 2593 } |
2169 | 2594 |
2170 /* | 2595 /* |
2171 ** Try to open an output file. The names "stdout" and "stderr" are | 2596 ** 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 | 2597 ** recognized and do the right thing. NULL is returned if the output |
2173 ** filename is "off". | 2598 ** filename is "off". |
2174 */ | 2599 */ |
2175 static FILE *output_file_open(const char *zFile){ | 2600 static FILE *output_file_open(const char *zFile){ |
2176 FILE *f; | 2601 FILE *f; |
2177 if( strcmp(zFile,"stdout")==0 ){ | 2602 if( strcmp(zFile,"stdout")==0 ){ |
2178 f = stdout; | 2603 f = stdout; |
2179 }else if( strcmp(zFile, "stderr")==0 ){ | 2604 }else if( strcmp(zFile, "stderr")==0 ){ |
2180 f = stderr; | 2605 f = stderr; |
2181 }else if( strcmp(zFile, "off")==0 ){ | 2606 }else if( strcmp(zFile, "off")==0 ){ |
2182 f = 0; | 2607 f = 0; |
2183 }else{ | 2608 }else{ |
2184 f = fopen(zFile, "wb"); | 2609 f = fopen(zFile, "wb"); |
2185 if( f==0 ){ | 2610 if( f==0 ){ |
2186 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); | 2611 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); |
2187 } | 2612 } |
2188 } | 2613 } |
2189 return f; | 2614 return f; |
2190 } | 2615 } |
2191 | 2616 |
| 2617 #if !defined(SQLITE_UNTESTABLE) |
| 2618 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) |
2192 /* | 2619 /* |
2193 ** A routine for handling output from sqlite3_trace(). | 2620 ** A routine for handling output from sqlite3_trace(). |
2194 */ | 2621 */ |
2195 static void sql_trace_callback(void *pArg, const char *z){ | 2622 static int sql_trace_callback( |
| 2623 unsigned mType, |
| 2624 void *pArg, |
| 2625 void *pP, |
| 2626 void *pX |
| 2627 ){ |
2196 FILE *f = (FILE*)pArg; | 2628 FILE *f = (FILE*)pArg; |
| 2629 UNUSED_PARAMETER(mType); |
| 2630 UNUSED_PARAMETER(pP); |
2197 if( f ){ | 2631 if( f ){ |
| 2632 const char *z = (const char*)pX; |
2198 int i = (int)strlen(z); | 2633 int i = (int)strlen(z); |
2199 while( i>0 && z[i-1]==';' ){ i--; } | 2634 while( i>0 && z[i-1]==';' ){ i--; } |
2200 utf8_printf(f, "%.*s;\n", i, z); | 2635 utf8_printf(f, "%.*s;\n", i, z); |
2201 } | 2636 } |
| 2637 return 0; |
2202 } | 2638 } |
| 2639 #endif |
| 2640 #endif |
2203 | 2641 |
2204 /* | 2642 /* |
2205 ** A no-op routine that runs with the ".breakpoint" doc-command. This is | 2643 ** A no-op routine that runs with the ".breakpoint" doc-command. This is |
2206 ** a useful spot to set a debugger breakpoint. | 2644 ** a useful spot to set a debugger breakpoint. |
2207 */ | 2645 */ |
2208 static void test_breakpoint(void){ | 2646 static void test_breakpoint(void){ |
2209 static int nCall = 0; | 2647 static int nCall = 0; |
2210 nCall++; | 2648 nCall++; |
2211 } | 2649 } |
2212 | 2650 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2351 /* | 2789 /* |
2352 ** Try to transfer data for table zTable. If an error is seen while | 2790 ** 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 | 2791 ** moving forward, try to go backwards. The backwards movement won't |
2354 ** work for WITHOUT ROWID tables. | 2792 ** work for WITHOUT ROWID tables. |
2355 */ | 2793 */ |
2356 static void tryToCloneData( | 2794 static void tryToCloneData( |
2357 ShellState *p, | 2795 ShellState *p, |
2358 sqlite3 *newDb, | 2796 sqlite3 *newDb, |
2359 const char *zTable | 2797 const char *zTable |
2360 ){ | 2798 ){ |
2361 sqlite3_stmt *pQuery = 0; | 2799 sqlite3_stmt *pQuery = 0; |
2362 sqlite3_stmt *pInsert = 0; | 2800 sqlite3_stmt *pInsert = 0; |
2363 char *zQuery = 0; | 2801 char *zQuery = 0; |
2364 char *zInsert = 0; | 2802 char *zInsert = 0; |
2365 int rc; | 2803 int rc; |
2366 int i, j, n; | 2804 int i, j, n; |
2367 int nTable = (int)strlen(zTable); | 2805 int nTable = (int)strlen(zTable); |
2368 int k = 0; | 2806 int k = 0; |
2369 int cnt = 0; | 2807 int cnt = 0; |
2370 const int spinRate = 10000; | 2808 const int spinRate = 10000; |
2371 | 2809 |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2588 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ | 3026 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ |
2589 res = sqlite3_column_int(pStmt,0); | 3027 res = sqlite3_column_int(pStmt,0); |
2590 } | 3028 } |
2591 sqlite3_finalize(pStmt); | 3029 sqlite3_finalize(pStmt); |
2592 return res; | 3030 return res; |
2593 } | 3031 } |
2594 | 3032 |
2595 /* | 3033 /* |
2596 ** Convert a 2-byte or 4-byte big-endian integer into a native integer | 3034 ** Convert a 2-byte or 4-byte big-endian integer into a native integer |
2597 */ | 3035 */ |
2598 unsigned int get2byteInt(unsigned char *a){ | 3036 static unsigned int get2byteInt(unsigned char *a){ |
2599 return (a[0]<<8) + a[1]; | 3037 return (a[0]<<8) + a[1]; |
2600 } | 3038 } |
2601 unsigned int get4byteInt(unsigned char *a){ | 3039 static unsigned int get4byteInt(unsigned char *a){ |
2602 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; | 3040 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; |
2603 } | 3041 } |
2604 | 3042 |
2605 /* | 3043 /* |
2606 ** Implementation of the ".info" command. | 3044 ** Implementation of the ".info" command. |
2607 ** | 3045 ** |
2608 ** Return 1 on error, 2 to exit, and 0 otherwise. | 3046 ** Return 1 on error, 2 to exit, and 0 otherwise. |
2609 */ | 3047 */ |
2610 static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ | 3048 static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ |
2611 static const struct { const char *zName; int ofst; } aField[] = { | 3049 static const struct { const char *zName; int ofst; } aField[] = { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2655 utf8_printf(p->out, "%-20s %d\n", "database page size:", i); | 3093 utf8_printf(p->out, "%-20s %d\n", "database page size:", i); |
2656 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); | 3094 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); |
2657 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); | 3095 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); |
2658 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); | 3096 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); |
2659 for(i=0; i<ArraySize(aField); i++){ | 3097 for(i=0; i<ArraySize(aField); i++){ |
2660 int ofst = aField[i].ofst; | 3098 int ofst = aField[i].ofst; |
2661 unsigned int val = get4byteInt(aHdr + ofst); | 3099 unsigned int val = get4byteInt(aHdr + ofst); |
2662 utf8_printf(p->out, "%-20s %u", aField[i].zName, val); | 3100 utf8_printf(p->out, "%-20s %u", aField[i].zName, val); |
2663 switch( ofst ){ | 3101 switch( ofst ){ |
2664 case 56: { | 3102 case 56: { |
2665 if( val==1 ) raw_printf(p->out, " (utf8)"); | 3103 if( val==1 ) raw_printf(p->out, " (utf8)"); |
2666 if( val==2 ) raw_printf(p->out, " (utf16le)"); | 3104 if( val==2 ) raw_printf(p->out, " (utf16le)"); |
2667 if( val==3 ) raw_printf(p->out, " (utf16be)"); | 3105 if( val==3 ) raw_printf(p->out, " (utf16be)"); |
2668 } | 3106 } |
2669 } | 3107 } |
2670 raw_printf(p->out, "\n"); | 3108 raw_printf(p->out, "\n"); |
2671 } | 3109 } |
2672 if( zDb==0 ){ | 3110 if( zDb==0 ){ |
2673 zSchemaTab = sqlite3_mprintf("main.sqlite_master"); | 3111 zSchemaTab = sqlite3_mprintf("main.sqlite_master"); |
2674 }else if( strcmp(zDb,"temp")==0 ){ | 3112 }else if( strcmp(zDb,"temp")==0 ){ |
2675 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master"); | 3113 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master"); |
2676 }else{ | 3114 }else{ |
2677 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb); | 3115 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb); |
(...skipping 19 matching lines...) Expand all Loading... |
2697 | 3135 |
2698 /* | 3136 /* |
2699 ** Print an out-of-memory message to stderr and return 1. | 3137 ** Print an out-of-memory message to stderr and return 1. |
2700 */ | 3138 */ |
2701 static int shellNomemError(void){ | 3139 static int shellNomemError(void){ |
2702 raw_printf(stderr, "Error: out of memory\n"); | 3140 raw_printf(stderr, "Error: out of memory\n"); |
2703 return 1; | 3141 return 1; |
2704 } | 3142 } |
2705 | 3143 |
2706 /* | 3144 /* |
| 3145 ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE |
| 3146 ** if they match and FALSE (0) if they do not match. |
| 3147 ** |
| 3148 ** Globbing rules: |
| 3149 ** |
| 3150 ** '*' Matches any sequence of zero or more characters. |
| 3151 ** |
| 3152 ** '?' Matches exactly one character. |
| 3153 ** |
| 3154 ** [...] Matches one character from the enclosed list of |
| 3155 ** characters. |
| 3156 ** |
| 3157 ** [^...] Matches one character not in the enclosed list. |
| 3158 ** |
| 3159 ** '#' Matches any sequence of one or more digits with an |
| 3160 ** optional + or - sign in front |
| 3161 ** |
| 3162 ** ' ' Any span of whitespace matches any other span of |
| 3163 ** whitespace. |
| 3164 ** |
| 3165 ** Extra whitespace at the end of z[] is ignored. |
| 3166 */ |
| 3167 static int testcase_glob(const char *zGlob, const char *z){ |
| 3168 int c, c2; |
| 3169 int invert; |
| 3170 int seen; |
| 3171 |
| 3172 while( (c = (*(zGlob++)))!=0 ){ |
| 3173 if( IsSpace(c) ){ |
| 3174 if( !IsSpace(*z) ) return 0; |
| 3175 while( IsSpace(*zGlob) ) zGlob++; |
| 3176 while( IsSpace(*z) ) z++; |
| 3177 }else if( c=='*' ){ |
| 3178 while( (c=(*(zGlob++))) == '*' || c=='?' ){ |
| 3179 if( c=='?' && (*(z++))==0 ) return 0; |
| 3180 } |
| 3181 if( c==0 ){ |
| 3182 return 1; |
| 3183 }else if( c=='[' ){ |
| 3184 while( *z && testcase_glob(zGlob-1,z)==0 ){ |
| 3185 z++; |
| 3186 } |
| 3187 return (*z)!=0; |
| 3188 } |
| 3189 while( (c2 = (*(z++)))!=0 ){ |
| 3190 while( c2!=c ){ |
| 3191 c2 = *(z++); |
| 3192 if( c2==0 ) return 0; |
| 3193 } |
| 3194 if( testcase_glob(zGlob,z) ) return 1; |
| 3195 } |
| 3196 return 0; |
| 3197 }else if( c=='?' ){ |
| 3198 if( (*(z++))==0 ) return 0; |
| 3199 }else if( c=='[' ){ |
| 3200 int prior_c = 0; |
| 3201 seen = 0; |
| 3202 invert = 0; |
| 3203 c = *(z++); |
| 3204 if( c==0 ) return 0; |
| 3205 c2 = *(zGlob++); |
| 3206 if( c2=='^' ){ |
| 3207 invert = 1; |
| 3208 c2 = *(zGlob++); |
| 3209 } |
| 3210 if( c2==']' ){ |
| 3211 if( c==']' ) seen = 1; |
| 3212 c2 = *(zGlob++); |
| 3213 } |
| 3214 while( c2 && c2!=']' ){ |
| 3215 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ |
| 3216 c2 = *(zGlob++); |
| 3217 if( c>=prior_c && c<=c2 ) seen = 1; |
| 3218 prior_c = 0; |
| 3219 }else{ |
| 3220 if( c==c2 ){ |
| 3221 seen = 1; |
| 3222 } |
| 3223 prior_c = c2; |
| 3224 } |
| 3225 c2 = *(zGlob++); |
| 3226 } |
| 3227 if( c2==0 || (seen ^ invert)==0 ) return 0; |
| 3228 }else if( c=='#' ){ |
| 3229 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++; |
| 3230 if( !IsDigit(z[0]) ) return 0; |
| 3231 z++; |
| 3232 while( IsDigit(z[0]) ){ z++; } |
| 3233 }else{ |
| 3234 if( c!=(*(z++)) ) return 0; |
| 3235 } |
| 3236 } |
| 3237 while( IsSpace(*z) ){ z++; } |
| 3238 return *z==0; |
| 3239 } |
| 3240 |
| 3241 |
| 3242 /* |
| 3243 ** Compare the string as a command-line option with either one or two |
| 3244 ** initial "-" characters. |
| 3245 */ |
| 3246 static int optionMatch(const char *zStr, const char *zOpt){ |
| 3247 if( zStr[0]!='-' ) return 0; |
| 3248 zStr++; |
| 3249 if( zStr[0]=='-' ) zStr++; |
| 3250 return strcmp(zStr, zOpt)==0; |
| 3251 } |
| 3252 |
| 3253 /* |
| 3254 ** Delete a file. |
| 3255 */ |
| 3256 int shellDeleteFile(const char *zFilename){ |
| 3257 int rc; |
| 3258 #ifdef _WIN32 |
| 3259 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename); |
| 3260 rc = _wunlink(z); |
| 3261 sqlite3_free(z); |
| 3262 #else |
| 3263 rc = unlink(zFilename); |
| 3264 #endif |
| 3265 return rc; |
| 3266 } |
| 3267 |
| 3268 |
| 3269 /* |
| 3270 ** The implementation of SQL scalar function fkey_collate_clause(), used |
| 3271 ** by the ".lint fkey-indexes" command. This scalar function is always |
| 3272 ** called with four arguments - the parent table name, the parent column name, |
| 3273 ** the child table name and the child column name. |
| 3274 ** |
| 3275 ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col') |
| 3276 ** |
| 3277 ** If either of the named tables or columns do not exist, this function |
| 3278 ** returns an empty string. An empty string is also returned if both tables |
| 3279 ** and columns exist but have the same default collation sequence. Or, |
| 3280 ** if both exist but the default collation sequences are different, this |
| 3281 ** function returns the string " COLLATE <parent-collation>", where |
| 3282 ** <parent-collation> is the default collation sequence of the parent column. |
| 3283 */ |
| 3284 static void shellFkeyCollateClause( |
| 3285 sqlite3_context *pCtx, |
| 3286 int nVal, |
| 3287 sqlite3_value **apVal |
| 3288 ){ |
| 3289 sqlite3 *db = sqlite3_context_db_handle(pCtx); |
| 3290 const char *zParent; |
| 3291 const char *zParentCol; |
| 3292 const char *zParentSeq; |
| 3293 const char *zChild; |
| 3294 const char *zChildCol; |
| 3295 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ |
| 3296 int rc; |
| 3297 |
| 3298 assert( nVal==4 ); |
| 3299 zParent = (const char*)sqlite3_value_text(apVal[0]); |
| 3300 zParentCol = (const char*)sqlite3_value_text(apVal[1]); |
| 3301 zChild = (const char*)sqlite3_value_text(apVal[2]); |
| 3302 zChildCol = (const char*)sqlite3_value_text(apVal[3]); |
| 3303 |
| 3304 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); |
| 3305 rc = sqlite3_table_column_metadata( |
| 3306 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0 |
| 3307 ); |
| 3308 if( rc==SQLITE_OK ){ |
| 3309 rc = sqlite3_table_column_metadata( |
| 3310 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0 |
| 3311 ); |
| 3312 } |
| 3313 |
| 3314 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){ |
| 3315 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq); |
| 3316 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); |
| 3317 sqlite3_free(z); |
| 3318 } |
| 3319 } |
| 3320 |
| 3321 |
| 3322 /* |
| 3323 ** The implementation of dot-command ".lint fkey-indexes". |
| 3324 */ |
| 3325 static int lintFkeyIndexes( |
| 3326 ShellState *pState, /* Current shell tool state */ |
| 3327 char **azArg, /* Array of arguments passed to dot command */ |
| 3328 int nArg /* Number of entries in azArg[] */ |
| 3329 ){ |
| 3330 sqlite3 *db = pState->db; /* Database handle to query "main" db of */ |
| 3331 FILE *out = pState->out; /* Stream to write non-error output to */ |
| 3332 int bVerbose = 0; /* If -verbose is present */ |
| 3333 int bGroupByParent = 0; /* If -groupbyparent is present */ |
| 3334 int i; /* To iterate through azArg[] */ |
| 3335 const char *zIndent = ""; /* How much to indent CREATE INDEX by */ |
| 3336 int rc; /* Return code */ |
| 3337 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */ |
| 3338 |
| 3339 /* |
| 3340 ** This SELECT statement returns one row for each foreign key constraint |
| 3341 ** in the schema of the main database. The column values are: |
| 3342 ** |
| 3343 ** 0. The text of an SQL statement similar to: |
| 3344 ** |
| 3345 ** "EXPLAIN QUERY PLAN SELECT rowid FROM child_table WHERE child_key=?" |
| 3346 ** |
| 3347 ** This is the same SELECT that the foreign keys implementation needs |
| 3348 ** to run internally on child tables. If there is an index that can |
| 3349 ** be used to optimize this query, then it can also be used by the FK |
| 3350 ** implementation to optimize DELETE or UPDATE statements on the parent |
| 3351 ** table. |
| 3352 ** |
| 3353 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by |
| 3354 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema |
| 3355 ** contains an index that can be used to optimize the query. |
| 3356 ** |
| 3357 ** 2. Human readable text that describes the child table and columns. e.g. |
| 3358 ** |
| 3359 ** "child_table(child_key1, child_key2)" |
| 3360 ** |
| 3361 ** 3. Human readable text that describes the parent table and columns. e.g. |
| 3362 ** |
| 3363 ** "parent_table(parent_key1, parent_key2)" |
| 3364 ** |
| 3365 ** 4. A full CREATE INDEX statement for an index that could be used to |
| 3366 ** optimize DELETE or UPDATE statements on the parent table. e.g. |
| 3367 ** |
| 3368 ** "CREATE INDEX child_table_child_key ON child_table(child_key)" |
| 3369 ** |
| 3370 ** 5. The name of the parent table. |
| 3371 ** |
| 3372 ** These six values are used by the C logic below to generate the report. |
| 3373 */ |
| 3374 const char *zSql = |
| 3375 "SELECT " |
| 3376 " 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '" |
| 3377 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " |
| 3378 " || fkey_collate_clause(f.[table], f.[to], s.name, f.[from]),' AND ')" |
| 3379 ", " |
| 3380 " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('" |
| 3381 " || group_concat('*=?', ' AND ') || ')'" |
| 3382 ", " |
| 3383 " s.name || '(' || group_concat(f.[from], ', ') || ')'" |
| 3384 ", " |
| 3385 " f.[table] || '(' || group_concat(COALESCE(f.[to], " |
| 3386 " (SELECT name FROM pragma_table_info(f.[table]) WHERE pk=seq+1)" |
| 3387 " )) || ')'" |
| 3388 ", " |
| 3389 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))" |
| 3390 " || ' ON ' || quote(s.name) || '('" |
| 3391 " || group_concat(quote(f.[from]) ||" |
| 3392 " fkey_collate_clause(f.[table], f.[to], s.name, f.[from]), ', ')" |
| 3393 " || ');'" |
| 3394 ", " |
| 3395 " f.[table] " |
| 3396 |
| 3397 "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f " |
| 3398 "GROUP BY s.name, f.id " |
| 3399 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)" |
| 3400 ; |
| 3401 |
| 3402 for(i=2; i<nArg; i++){ |
| 3403 int n = (int)strlen(azArg[i]); |
| 3404 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){ |
| 3405 bVerbose = 1; |
| 3406 } |
| 3407 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){ |
| 3408 bGroupByParent = 1; |
| 3409 zIndent = " "; |
| 3410 } |
| 3411 else{ |
| 3412 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", |
| 3413 azArg[0], azArg[1] |
| 3414 ); |
| 3415 return SQLITE_ERROR; |
| 3416 } |
| 3417 } |
| 3418 |
| 3419 /* Register the fkey_collate_clause() SQL function */ |
| 3420 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, |
| 3421 0, shellFkeyCollateClause, 0, 0 |
| 3422 ); |
| 3423 |
| 3424 |
| 3425 if( rc==SQLITE_OK ){ |
| 3426 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0); |
| 3427 } |
| 3428 if( rc==SQLITE_OK ){ |
| 3429 sqlite3_bind_int(pSql, 1, bGroupByParent); |
| 3430 } |
| 3431 |
| 3432 if( rc==SQLITE_OK ){ |
| 3433 int rc2; |
| 3434 char *zPrev = 0; |
| 3435 while( SQLITE_ROW==sqlite3_step(pSql) ){ |
| 3436 int res = -1; |
| 3437 sqlite3_stmt *pExplain = 0; |
| 3438 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0); |
| 3439 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1); |
| 3440 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2); |
| 3441 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3); |
| 3442 const char *zCI = (const char*)sqlite3_column_text(pSql, 4); |
| 3443 const char *zParent = (const char*)sqlite3_column_text(pSql, 5); |
| 3444 |
| 3445 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); |
| 3446 if( rc!=SQLITE_OK ) break; |
| 3447 if( SQLITE_ROW==sqlite3_step(pExplain) ){ |
| 3448 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3); |
| 3449 res = (0==sqlite3_strglob(zGlob, zPlan)); |
| 3450 } |
| 3451 rc = sqlite3_finalize(pExplain); |
| 3452 if( rc!=SQLITE_OK ) break; |
| 3453 |
| 3454 if( res<0 ){ |
| 3455 raw_printf(stderr, "Error: internal error"); |
| 3456 break; |
| 3457 }else{ |
| 3458 if( bGroupByParent |
| 3459 && (bVerbose || res==0) |
| 3460 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) |
| 3461 ){ |
| 3462 raw_printf(out, "-- Parent table %s\n", zParent); |
| 3463 sqlite3_free(zPrev); |
| 3464 zPrev = sqlite3_mprintf("%s", zParent); |
| 3465 } |
| 3466 |
| 3467 if( res==0 ){ |
| 3468 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); |
| 3469 }else if( bVerbose ){ |
| 3470 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", |
| 3471 zIndent, zFrom, zTarget |
| 3472 ); |
| 3473 } |
| 3474 } |
| 3475 } |
| 3476 sqlite3_free(zPrev); |
| 3477 |
| 3478 if( rc!=SQLITE_OK ){ |
| 3479 raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); |
| 3480 } |
| 3481 |
| 3482 rc2 = sqlite3_finalize(pSql); |
| 3483 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){ |
| 3484 rc = rc2; |
| 3485 raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); |
| 3486 } |
| 3487 }else{ |
| 3488 raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); |
| 3489 } |
| 3490 |
| 3491 return rc; |
| 3492 } |
| 3493 |
| 3494 /* |
| 3495 ** Implementation of ".lint" dot command. |
| 3496 */ |
| 3497 static int lintDotCommand( |
| 3498 ShellState *pState, /* Current shell tool state */ |
| 3499 char **azArg, /* Array of arguments passed to dot command */ |
| 3500 int nArg /* Number of entries in azArg[] */ |
| 3501 ){ |
| 3502 int n; |
| 3503 n = (nArg>=2 ? (int)strlen(azArg[1]) : 0); |
| 3504 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; |
| 3505 return lintFkeyIndexes(pState, azArg, nArg); |
| 3506 |
| 3507 usage: |
| 3508 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]); |
| 3509 raw_printf(stderr, "Where sub-commands are:\n"); |
| 3510 raw_printf(stderr, " fkey-indexes\n"); |
| 3511 return SQLITE_ERROR; |
| 3512 } |
| 3513 |
| 3514 |
| 3515 /* |
2707 ** If an input line begins with "." then invoke this routine to | 3516 ** If an input line begins with "." then invoke this routine to |
2708 ** process that line. | 3517 ** process that line. |
2709 ** | 3518 ** |
2710 ** Return 1 on error, 2 to exit, and 0 otherwise. | 3519 ** Return 1 on error, 2 to exit, and 0 otherwise. |
2711 */ | 3520 */ |
2712 static int do_meta_command(char *zLine, ShellState *p){ | 3521 static int do_meta_command(char *zLine, ShellState *p){ |
2713 int h = 1; | 3522 int h = 1; |
2714 int nArg = 0; | 3523 int nArg = 0; |
2715 int n, c; | 3524 int n, c; |
2716 int rc = 0; | 3525 int rc = 0; |
2717 char *azArg[50]; | 3526 char *azArg[50]; |
2718 | 3527 |
2719 /* Parse the input line into tokens. | 3528 /* Parse the input line into tokens. |
2720 */ | 3529 */ |
2721 while( zLine[h] && nArg<ArraySize(azArg) ){ | 3530 while( zLine[h] && nArg<ArraySize(azArg) ){ |
2722 while( IsSpace(zLine[h]) ){ h++; } | 3531 while( IsSpace(zLine[h]) ){ h++; } |
2723 if( zLine[h]==0 ) break; | 3532 if( zLine[h]==0 ) break; |
2724 if( zLine[h]=='\'' || zLine[h]=='"' ){ | 3533 if( zLine[h]=='\'' || zLine[h]=='"' ){ |
2725 int delim = zLine[h++]; | 3534 int delim = zLine[h++]; |
2726 azArg[nArg++] = &zLine[h]; | 3535 azArg[nArg++] = &zLine[h]; |
2727 while( zLine[h] && zLine[h]!=delim ){ | 3536 while( zLine[h] && zLine[h]!=delim ){ |
2728 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++; | 3537 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++; |
2729 h++; | 3538 h++; |
2730 } | 3539 } |
2731 if( zLine[h]==delim ){ | 3540 if( zLine[h]==delim ){ |
2732 zLine[h++] = 0; | 3541 zLine[h++] = 0; |
2733 } | 3542 } |
2734 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); | 3543 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); |
2735 }else{ | 3544 }else{ |
2736 azArg[nArg++] = &zLine[h]; | 3545 azArg[nArg++] = &zLine[h]; |
2737 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; } | 3546 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; } |
2738 if( zLine[h] ) zLine[h++] = 0; | 3547 if( zLine[h] ) zLine[h++] = 0; |
2739 resolve_backslashes(azArg[nArg-1]); | 3548 resolve_backslashes(azArg[nArg-1]); |
2740 } | 3549 } |
2741 } | 3550 } |
2742 | 3551 |
2743 /* Process the input line. | 3552 /* Process the input line. |
2744 */ | 3553 */ |
2745 if( nArg==0 ) return 0; /* no tokens, no error */ | 3554 if( nArg==0 ) return 0; /* no tokens, no error */ |
2746 n = strlen30(azArg[0]); | 3555 n = strlen30(azArg[0]); |
2747 c = azArg[0][0]; | 3556 c = azArg[0][0]; |
| 3557 |
| 3558 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 3559 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ |
| 3560 if( nArg!=2 ){ |
| 3561 raw_printf(stderr, "Usage: .auth ON|OFF\n"); |
| 3562 rc = 1; |
| 3563 goto meta_command_exit; |
| 3564 } |
| 3565 open_db(p, 0); |
| 3566 if( booleanValue(azArg[1]) ){ |
| 3567 sqlite3_set_authorizer(p->db, shellAuth, p); |
| 3568 }else{ |
| 3569 sqlite3_set_authorizer(p->db, 0, 0); |
| 3570 } |
| 3571 }else |
| 3572 #endif |
| 3573 |
2748 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) | 3574 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) |
2749 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) | 3575 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) |
2750 ){ | 3576 ){ |
2751 const char *zDestFile = 0; | 3577 const char *zDestFile = 0; |
2752 const char *zDb = 0; | 3578 const char *zDb = 0; |
2753 sqlite3 *pDest; | 3579 sqlite3 *pDest; |
2754 sqlite3_backup *pBackup; | 3580 sqlite3_backup *pBackup; |
2755 int j; | 3581 int j; |
2756 for(j=1; j<nArg; j++){ | 3582 for(j=1; j<nArg; j++){ |
2757 const char *z = azArg[j]; | 3583 const char *z = azArg[j]; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2806 bail_on_error = booleanValue(azArg[1]); | 3632 bail_on_error = booleanValue(azArg[1]); |
2807 }else{ | 3633 }else{ |
2808 raw_printf(stderr, "Usage: .bail on|off\n"); | 3634 raw_printf(stderr, "Usage: .bail on|off\n"); |
2809 rc = 1; | 3635 rc = 1; |
2810 } | 3636 } |
2811 }else | 3637 }else |
2812 | 3638 |
2813 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ | 3639 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ |
2814 if( nArg==2 ){ | 3640 if( nArg==2 ){ |
2815 if( booleanValue(azArg[1]) ){ | 3641 if( booleanValue(azArg[1]) ){ |
2816 setBinaryMode(p->out); | 3642 setBinaryMode(p->out, 1); |
2817 }else{ | 3643 }else{ |
2818 setTextMode(p->out); | 3644 setTextMode(p->out, 1); |
2819 } | 3645 } |
2820 }else{ | 3646 }else{ |
2821 raw_printf(stderr, "Usage: .binary on|off\n"); | 3647 raw_printf(stderr, "Usage: .binary on|off\n"); |
2822 rc = 1; | 3648 rc = 1; |
2823 } | 3649 } |
2824 }else | 3650 }else |
2825 | 3651 |
2826 /* The undocumented ".breakpoint" command causes a call to the no-op | 3652 /* The undocumented ".breakpoint" command causes a call to the no-op |
2827 ** routine named test_breakpoint(). | 3653 ** routine named test_breakpoint(). |
2828 */ | 3654 */ |
2829 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ | 3655 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ |
2830 test_breakpoint(); | 3656 test_breakpoint(); |
2831 }else | 3657 }else |
2832 | 3658 |
2833 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ | 3659 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ |
2834 if( nArg==2 ){ | 3660 if( nArg==2 ){ |
2835 p->countChanges = booleanValue(azArg[1]); | 3661 p->countChanges = booleanValue(azArg[1]); |
2836 }else{ | 3662 }else{ |
2837 raw_printf(stderr, "Usage: .changes on|off\n"); | 3663 raw_printf(stderr, "Usage: .changes on|off\n"); |
2838 rc = 1; | 3664 rc = 1; |
2839 } | 3665 } |
2840 }else | 3666 }else |
2841 | 3667 |
| 3668 /* Cancel output redirection, if it is currently set (by .testcase) |
| 3669 ** Then read the content of the testcase-out.txt file and compare against |
| 3670 ** azArg[1]. If there are differences, report an error and exit. |
| 3671 */ |
| 3672 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){ |
| 3673 char *zRes = 0; |
| 3674 output_reset(p); |
| 3675 if( nArg!=2 ){ |
| 3676 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); |
| 3677 rc = 2; |
| 3678 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ |
| 3679 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n"); |
| 3680 rc = 2; |
| 3681 }else if( testcase_glob(azArg[1],zRes)==0 ){ |
| 3682 utf8_printf(stderr, |
| 3683 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", |
| 3684 p->zTestcase, azArg[1], zRes); |
| 3685 rc = 2; |
| 3686 }else{ |
| 3687 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); |
| 3688 p->nCheck++; |
| 3689 } |
| 3690 sqlite3_free(zRes); |
| 3691 }else |
| 3692 |
2842 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ | 3693 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ |
2843 if( nArg==2 ){ | 3694 if( nArg==2 ){ |
2844 tryToClone(p, azArg[1]); | 3695 tryToClone(p, azArg[1]); |
2845 }else{ | 3696 }else{ |
2846 raw_printf(stderr, "Usage: .clone FILENAME\n"); | 3697 raw_printf(stderr, "Usage: .clone FILENAME\n"); |
2847 rc = 1; | 3698 rc = 1; |
2848 } | 3699 } |
2849 }else | 3700 }else |
2850 | 3701 |
2851 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ | 3702 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ |
2852 ShellState data; | 3703 ShellState data; |
2853 char *zErrMsg = 0; | 3704 char *zErrMsg = 0; |
2854 open_db(p, 0); | 3705 open_db(p, 0); |
2855 memcpy(&data, p, sizeof(data)); | 3706 memcpy(&data, p, sizeof(data)); |
2856 data.showHeader = 1; | 3707 data.showHeader = 0; |
2857 data.mode = MODE_Column; | 3708 data.cMode = data.mode = MODE_List; |
2858 data.colWidth[0] = 3; | 3709 sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": "); |
2859 data.colWidth[1] = 15; | |
2860 data.colWidth[2] = 58; | |
2861 data.cnt = 0; | 3710 data.cnt = 0; |
2862 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); | 3711 sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list", |
| 3712 callback, &data, &zErrMsg); |
2863 if( zErrMsg ){ | 3713 if( zErrMsg ){ |
2864 utf8_printf(stderr,"Error: %s\n", zErrMsg); | 3714 utf8_printf(stderr,"Error: %s\n", zErrMsg); |
2865 sqlite3_free(zErrMsg); | 3715 sqlite3_free(zErrMsg); |
2866 rc = 1; | 3716 rc = 1; |
2867 } | 3717 } |
2868 }else | 3718 }else |
2869 | 3719 |
2870 if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ | 3720 if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ |
2871 rc = shell_dbinfo_command(p, nArg, azArg); | 3721 rc = shell_dbinfo_command(p, nArg, azArg); |
2872 }else | 3722 }else |
2873 | 3723 |
2874 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ | 3724 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ |
2875 open_db(p, 0); | 3725 open_db(p, 0); |
2876 /* When playing back a "dump", the content might appear in an order | 3726 /* When playing back a "dump", the content might appear in an order |
2877 ** which causes immediate foreign key constraints to be violated. | 3727 ** which causes immediate foreign key constraints to be violated. |
2878 ** So disable foreign-key constraint enforcement to prevent problems. */ | 3728 ** So disable foreign-key constraint enforcement to prevent problems. */ |
2879 if( nArg!=1 && nArg!=2 ){ | 3729 if( nArg!=1 && nArg!=2 ){ |
2880 raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); | 3730 raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n"); |
2881 rc = 1; | 3731 rc = 1; |
2882 goto meta_command_exit; | 3732 goto meta_command_exit; |
2883 } | 3733 } |
2884 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); | 3734 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); |
2885 raw_printf(p->out, "BEGIN TRANSACTION;\n"); | 3735 raw_printf(p->out, "BEGIN TRANSACTION;\n"); |
2886 p->writableSchema = 0; | 3736 p->writableSchema = 0; |
2887 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); | 3737 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); |
2888 p->nErr = 0; | 3738 p->nErr = 0; |
2889 if( nArg==1 ){ | 3739 if( nArg==1 ){ |
2890 run_schema_dump_query(p, | 3740 run_schema_dump_query(p, |
2891 "SELECT name, type, sql FROM sqlite_master " | 3741 "SELECT name, type, sql FROM sqlite_master " |
2892 "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" | 3742 "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" |
2893 ); | 3743 ); |
2894 run_schema_dump_query(p, | 3744 run_schema_dump_query(p, |
2895 "SELECT name, type, sql FROM sqlite_master " | 3745 "SELECT name, type, sql FROM sqlite_master " |
2896 "WHERE name=='sqlite_sequence'" | 3746 "WHERE name=='sqlite_sequence'" |
2897 ); | 3747 ); |
2898 run_table_dump_query(p, | 3748 run_table_dump_query(p, |
2899 "SELECT sql FROM sqlite_master " | 3749 "SELECT sql FROM sqlite_master " |
2900 "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 | 3750 "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 |
2901 ); | 3751 ); |
2902 }else{ | 3752 }else{ |
2903 int i; | 3753 int i; |
2904 for(i=1; i<nArg; i++){ | 3754 for(i=1; i<nArg; i++){ |
(...skipping 24 matching lines...) Expand all Loading... |
2929 if( nArg==2 ){ | 3779 if( nArg==2 ){ |
2930 p->echoOn = booleanValue(azArg[1]); | 3780 p->echoOn = booleanValue(azArg[1]); |
2931 }else{ | 3781 }else{ |
2932 raw_printf(stderr, "Usage: .echo on|off\n"); | 3782 raw_printf(stderr, "Usage: .echo on|off\n"); |
2933 rc = 1; | 3783 rc = 1; |
2934 } | 3784 } |
2935 }else | 3785 }else |
2936 | 3786 |
2937 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ | 3787 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ |
2938 if( nArg==2 ){ | 3788 if( nArg==2 ){ |
2939 p->autoEQP = booleanValue(azArg[1]); | 3789 if( strcmp(azArg[1],"full")==0 ){ |
| 3790 p->autoEQP = 2; |
| 3791 }else{ |
| 3792 p->autoEQP = booleanValue(azArg[1]); |
| 3793 } |
2940 }else{ | 3794 }else{ |
2941 raw_printf(stderr, "Usage: .eqp on|off\n"); | 3795 raw_printf(stderr, "Usage: .eqp on|off|full\n"); |
2942 rc = 1; | 3796 rc = 1; |
2943 } | 3797 } |
2944 }else | 3798 }else |
2945 | 3799 |
2946 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ | 3800 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ |
2947 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); | 3801 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); |
2948 rc = 2; | 3802 rc = 2; |
2949 }else | 3803 }else |
2950 | 3804 |
2951 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ | 3805 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
2952 int val = nArg>=2 ? booleanValue(azArg[1]) : 1; | 3806 int val = 1; |
2953 if(val == 1) { | 3807 if( nArg>=2 ){ |
2954 if(!p->normalMode.valid) { | 3808 if( strcmp(azArg[1],"auto")==0 ){ |
2955 p->normalMode.valid = 1; | 3809 val = 99; |
2956 p->normalMode.mode = p->mode; | 3810 }else{ |
2957 p->normalMode.showHeader = p->showHeader; | 3811 val = booleanValue(azArg[1]); |
2958 memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); | |
2959 } | 3812 } |
2960 /* We could put this code under the !p->explainValid | 3813 } |
2961 ** condition so that it does not execute if we are already in | 3814 if( val==1 && p->mode!=MODE_Explain ){ |
2962 ** explain mode. However, always executing it allows us an easy | 3815 p->normalMode = p->mode; |
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; | 3816 p->mode = MODE_Explain; |
2968 p->showHeader = 1; | 3817 p->autoExplain = 0; |
2969 memset(p->colWidth,0,sizeof(p->colWidth)); | 3818 }else if( val==0 ){ |
2970 p->colWidth[0] = 4; /* addr */ | 3819 if( p->mode==MODE_Explain ) p->mode = p->normalMode; |
2971 p->colWidth[1] = 13; /* opcode */ | 3820 p->autoExplain = 0; |
2972 p->colWidth[2] = 4; /* P1 */ | 3821 }else if( val==99 ){ |
2973 p->colWidth[3] = 4; /* P2 */ | 3822 if( p->mode==MODE_Explain ) p->mode = p->normalMode; |
2974 p->colWidth[4] = 4; /* P3 */ | 3823 p->autoExplain = 1; |
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 } | 3824 } |
2984 }else | 3825 }else |
2985 | 3826 |
2986 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ | 3827 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ |
2987 ShellState data; | 3828 ShellState data; |
2988 char *zErrMsg = 0; | 3829 char *zErrMsg = 0; |
2989 int doStats = 0; | 3830 int doStats = 0; |
| 3831 memcpy(&data, p, sizeof(data)); |
| 3832 data.showHeader = 0; |
| 3833 data.cMode = data.mode = MODE_Semi; |
| 3834 if( nArg==2 && optionMatch(azArg[1], "indent") ){ |
| 3835 data.cMode = data.mode = MODE_Pretty; |
| 3836 nArg = 1; |
| 3837 } |
2990 if( nArg!=1 ){ | 3838 if( nArg!=1 ){ |
2991 raw_printf(stderr, "Usage: .fullschema\n"); | 3839 raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); |
2992 rc = 1; | 3840 rc = 1; |
2993 goto meta_command_exit; | 3841 goto meta_command_exit; |
2994 } | 3842 } |
2995 open_db(p, 0); | 3843 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, | 3844 rc = sqlite3_exec(p->db, |
3000 "SELECT sql FROM" | 3845 "SELECT sql FROM" |
3001 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | 3846 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
3002 " FROM sqlite_master UNION ALL" | 3847 " FROM sqlite_master UNION ALL" |
3003 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | 3848 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
3004 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | 3849 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " |
3005 "ORDER BY rowid", | 3850 "ORDER BY rowid", |
3006 callback, &data, &zErrMsg | 3851 callback, &data, &zErrMsg |
3007 ); | 3852 ); |
3008 if( rc==SQLITE_OK ){ | 3853 if( rc==SQLITE_OK ){ |
3009 sqlite3_stmt *pStmt; | 3854 sqlite3_stmt *pStmt; |
3010 rc = sqlite3_prepare_v2(p->db, | 3855 rc = sqlite3_prepare_v2(p->db, |
3011 "SELECT rowid FROM sqlite_master" | 3856 "SELECT rowid FROM sqlite_master" |
3012 " WHERE name GLOB 'sqlite_stat[134]'", | 3857 " WHERE name GLOB 'sqlite_stat[134]'", |
3013 -1, &pStmt, 0); | 3858 -1, &pStmt, 0); |
3014 doStats = sqlite3_step(pStmt)==SQLITE_ROW; | 3859 doStats = sqlite3_step(pStmt)==SQLITE_ROW; |
3015 sqlite3_finalize(pStmt); | 3860 sqlite3_finalize(pStmt); |
3016 } | 3861 } |
3017 if( doStats==0 ){ | 3862 if( doStats==0 ){ |
3018 raw_printf(p->out, "/* No STAT tables available */\n"); | 3863 raw_printf(p->out, "/* No STAT tables available */\n"); |
3019 }else{ | 3864 }else{ |
3020 raw_printf(p->out, "ANALYZE sqlite_master;\n"); | 3865 raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
3021 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'", | 3866 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'", |
3022 callback, &data, &zErrMsg); | 3867 callback, &data, &zErrMsg); |
3023 data.mode = MODE_Insert; | 3868 data.cMode = data.mode = MODE_Insert; |
3024 data.zDestTable = "sqlite_stat1"; | 3869 data.zDestTable = "sqlite_stat1"; |
3025 shell_exec(p->db, "SELECT * FROM sqlite_stat1", | 3870 shell_exec(p->db, "SELECT * FROM sqlite_stat1", |
3026 shell_callback, &data,&zErrMsg); | 3871 shell_callback, &data,&zErrMsg); |
3027 data.zDestTable = "sqlite_stat3"; | 3872 data.zDestTable = "sqlite_stat3"; |
3028 shell_exec(p->db, "SELECT * FROM sqlite_stat3", | 3873 shell_exec(p->db, "SELECT * FROM sqlite_stat3", |
3029 shell_callback, &data,&zErrMsg); | 3874 shell_callback, &data,&zErrMsg); |
3030 data.zDestTable = "sqlite_stat4"; | 3875 data.zDestTable = "sqlite_stat4"; |
3031 shell_exec(p->db, "SELECT * FROM sqlite_stat4", | 3876 shell_exec(p->db, "SELECT * FROM sqlite_stat4", |
3032 shell_callback, &data, &zErrMsg); | 3877 shell_callback, &data, &zErrMsg); |
3033 raw_printf(p->out, "ANALYZE sqlite_master;\n"); | 3878 raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3131 xCloser(sCtx.in); | 3976 xCloser(sCtx.in); |
3132 return 1; | 3977 return 1; |
3133 } | 3978 } |
3134 nByte = strlen30(zSql); | 3979 nByte = strlen30(zSql); |
3135 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | 3980 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
3136 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ | 3981 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ |
3137 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ | 3982 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ |
3138 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); | 3983 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); |
3139 char cSep = '('; | 3984 char cSep = '('; |
3140 while( xRead(&sCtx) ){ | 3985 while( xRead(&sCtx) ){ |
3141 zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCtx.z); | 3986 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); |
3142 cSep = ','; | 3987 cSep = ','; |
3143 if( sCtx.cTerm!=sCtx.cColSep ) break; | 3988 if( sCtx.cTerm!=sCtx.cColSep ) break; |
3144 } | 3989 } |
3145 if( cSep=='(' ){ | 3990 if( cSep=='(' ){ |
3146 sqlite3_free(zCreate); | 3991 sqlite3_free(zCreate); |
3147 sqlite3_free(sCtx.z); | 3992 sqlite3_free(sCtx.z); |
3148 xCloser(sCtx.in); | 3993 xCloser(sCtx.in); |
3149 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); | 3994 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); |
3150 return 1; | 3995 return 1; |
3151 } | 3996 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 } | 4083 } |
3239 } | 4084 } |
3240 }while( sCtx.cTerm!=EOF ); | 4085 }while( sCtx.cTerm!=EOF ); |
3241 | 4086 |
3242 xCloser(sCtx.in); | 4087 xCloser(sCtx.in); |
3243 sqlite3_free(sCtx.z); | 4088 sqlite3_free(sCtx.z); |
3244 sqlite3_finalize(pStmt); | 4089 sqlite3_finalize(pStmt); |
3245 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); | 4090 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); |
3246 }else | 4091 }else |
3247 | 4092 |
3248 if( c=='i' && (strncmp(azArg[0], "indices", n)==0 | 4093 #ifndef SQLITE_UNTESTABLE |
3249 || strncmp(azArg[0], "indexes", n)==0) ){ | 4094 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ |
3250 ShellState data; | 4095 char *zSql; |
3251 char *zErrMsg = 0; | 4096 char *zCollist = 0; |
3252 open_db(p, 0); | 4097 sqlite3_stmt *pStmt; |
3253 memcpy(&data, p, sizeof(data)); | 4098 int tnum = 0; |
3254 data.showHeader = 0; | 4099 int i; |
3255 data.mode = MODE_List; | 4100 if( nArg!=3 ){ |
3256 if( nArg==1 ){ | 4101 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"); |
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; | 4102 rc = 1; |
3281 goto meta_command_exit; | 4103 goto meta_command_exit; |
3282 } | 4104 } |
3283 if( zErrMsg ){ | 4105 open_db(p, 0); |
3284 utf8_printf(stderr,"Error: %s\n", zErrMsg); | 4106 zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" |
3285 sqlite3_free(zErrMsg); | 4107 " WHERE name='%q' AND type='index'", azArg[1]); |
| 4108 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 4109 sqlite3_free(zSql); |
| 4110 if( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 4111 tnum = sqlite3_column_int(pStmt, 0); |
| 4112 } |
| 4113 sqlite3_finalize(pStmt); |
| 4114 if( tnum==0 ){ |
| 4115 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); |
3286 rc = 1; | 4116 rc = 1; |
3287 }else if( rc != SQLITE_OK ){ | 4117 goto meta_command_exit; |
3288 raw_printf(stderr, | 4118 } |
3289 "Error: querying sqlite_master and sqlite_temp_master\n"); | 4119 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); |
| 4120 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
| 4121 sqlite3_free(zSql); |
| 4122 i = 0; |
| 4123 while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 4124 char zLabel[20]; |
| 4125 const char *zCol = (const char*)sqlite3_column_text(pStmt,2); |
| 4126 i++; |
| 4127 if( zCol==0 ){ |
| 4128 if( sqlite3_column_int(pStmt,1)==-1 ){ |
| 4129 zCol = "_ROWID_"; |
| 4130 }else{ |
| 4131 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); |
| 4132 zCol = zLabel; |
| 4133 } |
| 4134 } |
| 4135 if( zCollist==0 ){ |
| 4136 zCollist = sqlite3_mprintf("\"%w\"", zCol); |
| 4137 }else{ |
| 4138 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); |
| 4139 } |
| 4140 } |
| 4141 sqlite3_finalize(pStmt); |
| 4142 zSql = sqlite3_mprintf( |
| 4143 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID", |
| 4144 azArg[2], zCollist, zCollist); |
| 4145 sqlite3_free(zCollist); |
| 4146 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); |
| 4147 if( rc==SQLITE_OK ){ |
| 4148 rc = sqlite3_exec(p->db, zSql, 0, 0, 0); |
| 4149 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); |
| 4150 if( rc ){ |
| 4151 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); |
| 4152 }else{ |
| 4153 utf8_printf(stdout, "%s;\n", zSql); |
| 4154 raw_printf(stdout, |
| 4155 "WARNING: writing to an imposter table will corrupt the index!\n" |
| 4156 ); |
| 4157 } |
| 4158 }else{ |
| 4159 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); |
3290 rc = 1; | 4160 rc = 1; |
3291 } | 4161 } |
| 4162 sqlite3_free(zSql); |
3292 }else | 4163 }else |
| 4164 #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */ |
3293 | 4165 |
3294 #ifdef SQLITE_ENABLE_IOTRACE | 4166 #ifdef SQLITE_ENABLE_IOTRACE |
3295 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ | 4167 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ |
3296 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); | 4168 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); |
3297 if( iotrace && iotrace!=stdout ) fclose(iotrace); | 4169 if( iotrace && iotrace!=stdout ) fclose(iotrace); |
3298 iotrace = 0; | 4170 iotrace = 0; |
3299 if( nArg<2 ){ | 4171 if( nArg<2 ){ |
3300 sqlite3IoTrace = 0; | 4172 sqlite3IoTrace = 0; |
3301 }else if( strcmp(azArg[1], "-")==0 ){ | 4173 }else if( strcmp(azArg[1], "-")==0 ){ |
3302 sqlite3IoTrace = iotracePrintf; | 4174 sqlite3IoTrace = iotracePrintf; |
3303 iotrace = stdout; | 4175 iotrace = stdout; |
3304 }else{ | 4176 }else{ |
3305 iotrace = fopen(azArg[1], "w"); | 4177 iotrace = fopen(azArg[1], "w"); |
3306 if( iotrace==0 ){ | 4178 if( iotrace==0 ){ |
3307 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); | 4179 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); |
3308 sqlite3IoTrace = 0; | 4180 sqlite3IoTrace = 0; |
3309 rc = 1; | 4181 rc = 1; |
3310 }else{ | 4182 }else{ |
3311 sqlite3IoTrace = iotracePrintf; | 4183 sqlite3IoTrace = iotracePrintf; |
3312 } | 4184 } |
3313 } | 4185 } |
3314 }else | 4186 }else |
3315 #endif | 4187 #endif |
| 4188 |
3316 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ | 4189 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ |
3317 static const struct { | 4190 static const struct { |
3318 const char *zLimitName; /* Name of a limit */ | 4191 const char *zLimitName; /* Name of a limit */ |
3319 int limitCode; /* Integer code for that limit */ | 4192 int limitCode; /* Integer code for that limit */ |
3320 } aLimit[] = { | 4193 } aLimit[] = { |
3321 { "length", SQLITE_LIMIT_LENGTH }, | 4194 { "length", SQLITE_LIMIT_LENGTH }, |
3322 { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, | 4195 { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, |
3323 { "column", SQLITE_LIMIT_COLUMN }, | 4196 { "column", SQLITE_LIMIT_COLUMN }, |
3324 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, | 4197 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, |
3325 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, | 4198 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, |
3326 { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, | 4199 { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, |
3327 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, | 4200 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, |
3328 { "attached", SQLITE_LIMIT_ATTACHED }, | 4201 { "attached", SQLITE_LIMIT_ATTACHED }, |
3329 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, | 4202 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, |
3330 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, | 4203 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, |
3331 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, | 4204 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, |
3332 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, | 4205 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, |
3333 }; | 4206 }; |
3334 int i, n2; | 4207 int i, n2; |
3335 open_db(p, 0); | 4208 open_db(p, 0); |
3336 if( nArg==1 ){ | 4209 if( nArg==1 ){ |
3337 for(i=0; i<ArraySize(aLimit); i++){ | 4210 for(i=0; i<ArraySize(aLimit); i++){ |
3338 printf("%20s %d\n", aLimit[i].zLimitName, | 4211 printf("%20s %d\n", aLimit[i].zLimitName, |
3339 sqlite3_limit(p->db, aLimit[i].limitCode, -1)); | 4212 sqlite3_limit(p->db, aLimit[i].limitCode, -1)); |
3340 } | 4213 } |
3341 }else if( nArg>3 ){ | 4214 }else if( nArg>3 ){ |
3342 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); | 4215 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); |
3343 rc = 1; | 4216 rc = 1; |
3344 goto meta_command_exit; | 4217 goto meta_command_exit; |
3345 }else{ | 4218 }else{ |
3346 int iLimit = -1; | 4219 int iLimit = -1; |
3347 n2 = strlen30(azArg[1]); | 4220 n2 = strlen30(azArg[1]); |
3348 for(i=0; i<ArraySize(aLimit); i++){ | 4221 for(i=0; i<ArraySize(aLimit); i++){ |
(...skipping 16 matching lines...) Expand all Loading... |
3365 } | 4238 } |
3366 if( nArg==3 ){ | 4239 if( nArg==3 ){ |
3367 sqlite3_limit(p->db, aLimit[iLimit].limitCode, | 4240 sqlite3_limit(p->db, aLimit[iLimit].limitCode, |
3368 (int)integerValue(azArg[2])); | 4241 (int)integerValue(azArg[2])); |
3369 } | 4242 } |
3370 printf("%20s %d\n", aLimit[iLimit].zLimitName, | 4243 printf("%20s %d\n", aLimit[iLimit].zLimitName, |
3371 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); | 4244 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); |
3372 } | 4245 } |
3373 }else | 4246 }else |
3374 | 4247 |
| 4248 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){ |
| 4249 open_db(p, 0); |
| 4250 lintDotCommand(p, azArg, nArg); |
| 4251 }else |
| 4252 |
3375 #ifndef SQLITE_OMIT_LOAD_EXTENSION | 4253 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
3376 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ | 4254 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ |
3377 const char *zFile, *zProc; | 4255 const char *zFile, *zProc; |
3378 char *zErrMsg = 0; | 4256 char *zErrMsg = 0; |
3379 if( nArg<2 ){ | 4257 if( nArg<2 ){ |
3380 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); | 4258 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); |
3381 rc = 1; | 4259 rc = 1; |
3382 goto meta_command_exit; | 4260 goto meta_command_exit; |
3383 } | 4261 } |
3384 zFile = azArg[1]; | 4262 zFile = azArg[1]; |
(...skipping 18 matching lines...) Expand all Loading... |
3403 p->pLog = output_file_open(zFile); | 4281 p->pLog = output_file_open(zFile); |
3404 } | 4282 } |
3405 }else | 4283 }else |
3406 | 4284 |
3407 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ | 4285 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ |
3408 const char *zMode = nArg>=2 ? azArg[1] : ""; | 4286 const char *zMode = nArg>=2 ? azArg[1] : ""; |
3409 int n2 = (int)strlen(zMode); | 4287 int n2 = (int)strlen(zMode); |
3410 int c2 = zMode[0]; | 4288 int c2 = zMode[0]; |
3411 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ | 4289 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ |
3412 p->mode = MODE_Line; | 4290 p->mode = MODE_Line; |
| 4291 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); |
3413 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ | 4292 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ |
3414 p->mode = MODE_Column; | 4293 p->mode = MODE_Column; |
| 4294 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); |
3415 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ | 4295 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ |
3416 p->mode = MODE_List; | 4296 p->mode = MODE_List; |
| 4297 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); |
| 4298 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); |
3417 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ | 4299 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ |
3418 p->mode = MODE_Html; | 4300 p->mode = MODE_Html; |
3419 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ | 4301 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ |
3420 p->mode = MODE_Tcl; | 4302 p->mode = MODE_Tcl; |
3421 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); | 4303 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); |
| 4304 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); |
3422 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ | 4305 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ |
3423 p->mode = MODE_Csv; | 4306 p->mode = MODE_Csv; |
3424 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); | 4307 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); |
3425 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); | 4308 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); |
3426 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ | 4309 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ |
3427 p->mode = MODE_List; | 4310 p->mode = MODE_List; |
3428 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); | 4311 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
3429 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ | 4312 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
3430 p->mode = MODE_Insert; | 4313 p->mode = MODE_Insert; |
3431 set_table_name(p, nArg>=3 ? azArg[2] : "table"); | 4314 set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 4315 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ |
| 4316 p->mode = MODE_Quote; |
3432 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ | 4317 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
3433 p->mode = MODE_Ascii; | 4318 p->mode = MODE_Ascii; |
3434 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); | 4319 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
3435 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); | 4320 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
3436 }else { | 4321 }else { |
3437 raw_printf(stderr, "Error: mode should be one of: " | 4322 raw_printf(stderr, "Error: mode should be one of: " |
3438 "ascii column csv html insert line list tabs tcl\n"); | 4323 "ascii column csv html insert line list quote tabs tcl\n"); |
3439 rc = 1; | 4324 rc = 1; |
3440 } | 4325 } |
| 4326 p->cMode = p->mode; |
3441 }else | 4327 }else |
3442 | 4328 |
3443 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ | 4329 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ |
3444 if( nArg==2 ){ | 4330 if( nArg==2 ){ |
3445 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, | 4331 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, |
3446 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); | 4332 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); |
3447 }else{ | 4333 }else{ |
3448 raw_printf(stderr, "Usage: .nullvalue STRING\n"); | 4334 raw_printf(stderr, "Usage: .nullvalue STRING\n"); |
3449 rc = 1; | 4335 rc = 1; |
3450 } | 4336 } |
3451 }else | 4337 }else |
3452 | 4338 |
3453 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ | 4339 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ |
3454 sqlite3 *savedDb = p->db; | 4340 char *zNewFilename; /* Name of the database file to open */ |
3455 const char *zSavedFilename = p->zDbFilename; | 4341 int iName = 1; /* Index in azArg[] of the filename */ |
3456 char *zNewFilename = 0; | 4342 int newFlag = 0; /* True to delete file before opening */ |
| 4343 /* Close the existing database */ |
| 4344 session_close_all(p); |
| 4345 sqlite3_close(p->db); |
3457 p->db = 0; | 4346 p->db = 0; |
3458 if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]); | 4347 sqlite3_free(p->zFreeOnClose); |
3459 p->zDbFilename = zNewFilename; | 4348 p->zFreeOnClose = 0; |
3460 open_db(p, 1); | 4349 /* Check for command-line arguments */ |
3461 if( p->db!=0 ){ | 4350 for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ |
3462 sqlite3_close(savedDb); | 4351 const char *z = azArg[iName]; |
3463 sqlite3_free(p->zFreeOnClose); | 4352 if( optionMatch(z,"new") ){ |
3464 p->zFreeOnClose = zNewFilename; | 4353 newFlag = 1; |
3465 }else{ | 4354 }else if( z[0]=='-' ){ |
3466 sqlite3_free(zNewFilename); | 4355 utf8_printf(stderr, "unknown option: %s\n", z); |
3467 p->db = savedDb; | 4356 rc = 1; |
3468 p->zDbFilename = zSavedFilename; | 4357 goto meta_command_exit; |
| 4358 } |
| 4359 } |
| 4360 /* If a filename is specified, try to open it first */ |
| 4361 zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0; |
| 4362 if( zNewFilename ){ |
| 4363 if( newFlag ) shellDeleteFile(zNewFilename); |
| 4364 p->zDbFilename = zNewFilename; |
| 4365 open_db(p, 1); |
| 4366 if( p->db==0 ){ |
| 4367 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); |
| 4368 sqlite3_free(zNewFilename); |
| 4369 }else{ |
| 4370 p->zFreeOnClose = zNewFilename; |
| 4371 } |
| 4372 } |
| 4373 if( p->db==0 ){ |
| 4374 /* As a fall-back open a TEMP database */ |
| 4375 p->zDbFilename = 0; |
| 4376 open_db(p, 0); |
3469 } | 4377 } |
3470 }else | 4378 }else |
3471 | 4379 |
3472 if( c=='o' | 4380 if( c=='o' |
3473 && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0) | 4381 && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0) |
3474 ){ | 4382 ){ |
3475 const char *zFile = nArg>=2 ? azArg[1] : "stdout"; | 4383 const char *zFile = nArg>=2 ? azArg[1] : "stdout"; |
3476 if( nArg>2 ){ | 4384 if( nArg>2 ){ |
3477 utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]); | 4385 utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]); |
3478 rc = 1; | 4386 rc = 1; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3620 rc = 1; | 4528 rc = 1; |
3621 } | 4529 } |
3622 }else | 4530 }else |
3623 | 4531 |
3624 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ | 4532 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ |
3625 ShellState data; | 4533 ShellState data; |
3626 char *zErrMsg = 0; | 4534 char *zErrMsg = 0; |
3627 open_db(p, 0); | 4535 open_db(p, 0); |
3628 memcpy(&data, p, sizeof(data)); | 4536 memcpy(&data, p, sizeof(data)); |
3629 data.showHeader = 0; | 4537 data.showHeader = 0; |
3630 data.mode = MODE_Semi; | 4538 data.cMode = data.mode = MODE_Semi; |
3631 if( nArg==2 ){ | 4539 if( nArg>=2 && optionMatch(azArg[1], "indent") ){ |
| 4540 data.cMode = data.mode = MODE_Pretty; |
| 4541 nArg--; |
| 4542 if( nArg==2 ) azArg[1] = azArg[2]; |
| 4543 } |
| 4544 if( nArg==2 && azArg[1][0]!='-' ){ |
3632 int i; | 4545 int i; |
3633 for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); | 4546 for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); |
3634 if( strcmp(azArg[1],"sqlite_master")==0 ){ | 4547 if( strcmp(azArg[1],"sqlite_master")==0 ){ |
3635 char *new_argv[2], *new_colv[2]; | 4548 char *new_argv[2], *new_colv[2]; |
3636 new_argv[0] = "CREATE TABLE sqlite_master (\n" | 4549 new_argv[0] = "CREATE TABLE sqlite_master (\n" |
3637 " type text,\n" | 4550 " type text,\n" |
3638 " name text,\n" | 4551 " name text,\n" |
3639 " tbl_name text,\n" | 4552 " tbl_name text,\n" |
3640 " rootpage integer,\n" | 4553 " rootpage integer,\n" |
3641 " sql text\n" | 4554 " sql text\n" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3676 rc = sqlite3_exec(p->db, | 4589 rc = sqlite3_exec(p->db, |
3677 "SELECT sql FROM " | 4590 "SELECT sql FROM " |
3678 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" | 4591 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
3679 " FROM sqlite_master UNION ALL" | 4592 " FROM sqlite_master UNION ALL" |
3680 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " | 4593 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
3681 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | 4594 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " |
3682 "ORDER BY rowid", | 4595 "ORDER BY rowid", |
3683 callback, &data, &zErrMsg | 4596 callback, &data, &zErrMsg |
3684 ); | 4597 ); |
3685 }else{ | 4598 }else{ |
3686 raw_printf(stderr, "Usage: .schema ?LIKE-PATTERN?\n"); | 4599 raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); |
3687 rc = 1; | 4600 rc = 1; |
3688 goto meta_command_exit; | 4601 goto meta_command_exit; |
3689 } | 4602 } |
3690 if( zErrMsg ){ | 4603 if( zErrMsg ){ |
3691 utf8_printf(stderr,"Error: %s\n", zErrMsg); | 4604 utf8_printf(stderr,"Error: %s\n", zErrMsg); |
3692 sqlite3_free(zErrMsg); | 4605 sqlite3_free(zErrMsg); |
3693 rc = 1; | 4606 rc = 1; |
3694 }else if( rc != SQLITE_OK ){ | 4607 }else if( rc != SQLITE_OK ){ |
3695 raw_printf(stderr,"Error: querying schema information\n"); | 4608 raw_printf(stderr,"Error: querying schema information\n"); |
3696 rc = 1; | 4609 rc = 1; |
3697 }else{ | 4610 }else{ |
3698 rc = 0; | 4611 rc = 0; |
3699 } | 4612 } |
3700 }else | 4613 }else |
3701 | 4614 |
3702 | |
3703 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) | 4615 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) |
3704 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ | 4616 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ |
3705 extern int sqlite3SelectTrace; | |
3706 sqlite3SelectTrace = integerValue(azArg[1]); | 4617 sqlite3SelectTrace = integerValue(azArg[1]); |
3707 }else | 4618 }else |
3708 #endif | 4619 #endif |
3709 | 4620 |
| 4621 #if defined(SQLITE_ENABLE_SESSION) |
| 4622 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ |
| 4623 OpenSession *pSession = &p->aSession[0]; |
| 4624 char **azCmd = &azArg[1]; |
| 4625 int iSes = 0; |
| 4626 int nCmd = nArg - 1; |
| 4627 int i; |
| 4628 if( nArg<=1 ) goto session_syntax_error; |
| 4629 open_db(p, 0); |
| 4630 if( nArg>=3 ){ |
| 4631 for(iSes=0; iSes<p->nSession; iSes++){ |
| 4632 if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break; |
| 4633 } |
| 4634 if( iSes<p->nSession ){ |
| 4635 pSession = &p->aSession[iSes]; |
| 4636 azCmd++; |
| 4637 nCmd--; |
| 4638 }else{ |
| 4639 pSession = &p->aSession[0]; |
| 4640 iSes = 0; |
| 4641 } |
| 4642 } |
| 4643 |
| 4644 /* .session attach TABLE |
| 4645 ** Invoke the sqlite3session_attach() interface to attach a particular |
| 4646 ** table so that it is never filtered. |
| 4647 */ |
| 4648 if( strcmp(azCmd[0],"attach")==0 ){ |
| 4649 if( nCmd!=2 ) goto session_syntax_error; |
| 4650 if( pSession->p==0 ){ |
| 4651 session_not_open: |
| 4652 raw_printf(stderr, "ERROR: No sessions are open\n"); |
| 4653 }else{ |
| 4654 rc = sqlite3session_attach(pSession->p, azCmd[1]); |
| 4655 if( rc ){ |
| 4656 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); |
| 4657 rc = 0; |
| 4658 } |
| 4659 } |
| 4660 }else |
| 4661 |
| 4662 /* .session changeset FILE |
| 4663 ** .session patchset FILE |
| 4664 ** Write a changeset or patchset into a file. The file is overwritten. |
| 4665 */ |
| 4666 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){ |
| 4667 FILE *out = 0; |
| 4668 if( nCmd!=2 ) goto session_syntax_error; |
| 4669 if( pSession->p==0 ) goto session_not_open; |
| 4670 out = fopen(azCmd[1], "wb"); |
| 4671 if( out==0 ){ |
| 4672 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1])
; |
| 4673 }else{ |
| 4674 int szChng; |
| 4675 void *pChng; |
| 4676 if( azCmd[0][0]=='c' ){ |
| 4677 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); |
| 4678 }else{ |
| 4679 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); |
| 4680 } |
| 4681 if( rc ){ |
| 4682 printf("Error: error code %d\n", rc); |
| 4683 rc = 0; |
| 4684 } |
| 4685 if( pChng |
| 4686 && fwrite(pChng, szChng, 1, out)!=1 ){ |
| 4687 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", |
| 4688 szChng); |
| 4689 } |
| 4690 sqlite3_free(pChng); |
| 4691 fclose(out); |
| 4692 } |
| 4693 }else |
| 4694 |
| 4695 /* .session close |
| 4696 ** Close the identified session |
| 4697 */ |
| 4698 if( strcmp(azCmd[0], "close")==0 ){ |
| 4699 if( nCmd!=1 ) goto session_syntax_error; |
| 4700 if( p->nSession ){ |
| 4701 session_close(pSession); |
| 4702 p->aSession[iSes] = p->aSession[--p->nSession]; |
| 4703 } |
| 4704 }else |
| 4705 |
| 4706 /* .session enable ?BOOLEAN? |
| 4707 ** Query or set the enable flag |
| 4708 */ |
| 4709 if( strcmp(azCmd[0], "enable")==0 ){ |
| 4710 int ii; |
| 4711 if( nCmd>2 ) goto session_syntax_error; |
| 4712 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); |
| 4713 if( p->nSession ){ |
| 4714 ii = sqlite3session_enable(pSession->p, ii); |
| 4715 utf8_printf(p->out, "session %s enable flag = %d\n", |
| 4716 pSession->zName, ii); |
| 4717 } |
| 4718 }else |
| 4719 |
| 4720 /* .session filter GLOB .... |
| 4721 ** Set a list of GLOB patterns of table names to be excluded. |
| 4722 */ |
| 4723 if( strcmp(azCmd[0], "filter")==0 ){ |
| 4724 int ii, nByte; |
| 4725 if( nCmd<2 ) goto session_syntax_error; |
| 4726 if( p->nSession ){ |
| 4727 for(ii=0; ii<pSession->nFilter; ii++){ |
| 4728 sqlite3_free(pSession->azFilter[ii]); |
| 4729 } |
| 4730 sqlite3_free(pSession->azFilter); |
| 4731 nByte = sizeof(pSession->azFilter[0])*(nCmd-1); |
| 4732 pSession->azFilter = sqlite3_malloc( nByte ); |
| 4733 if( pSession->azFilter==0 ){ |
| 4734 raw_printf(stderr, "Error: out or memory\n"); |
| 4735 exit(1); |
| 4736 } |
| 4737 for(ii=1; ii<nCmd; ii++){ |
| 4738 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); |
| 4739 } |
| 4740 pSession->nFilter = ii-1; |
| 4741 } |
| 4742 }else |
| 4743 |
| 4744 /* .session indirect ?BOOLEAN? |
| 4745 ** Query or set the indirect flag |
| 4746 */ |
| 4747 if( strcmp(azCmd[0], "indirect")==0 ){ |
| 4748 int ii; |
| 4749 if( nCmd>2 ) goto session_syntax_error; |
| 4750 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); |
| 4751 if( p->nSession ){ |
| 4752 ii = sqlite3session_indirect(pSession->p, ii); |
| 4753 utf8_printf(p->out, "session %s indirect flag = %d\n", |
| 4754 pSession->zName, ii); |
| 4755 } |
| 4756 }else |
| 4757 |
| 4758 /* .session isempty |
| 4759 ** Determine if the session is empty |
| 4760 */ |
| 4761 if( strcmp(azCmd[0], "isempty")==0 ){ |
| 4762 int ii; |
| 4763 if( nCmd!=1 ) goto session_syntax_error; |
| 4764 if( p->nSession ){ |
| 4765 ii = sqlite3session_isempty(pSession->p); |
| 4766 utf8_printf(p->out, "session %s isempty flag = %d\n", |
| 4767 pSession->zName, ii); |
| 4768 } |
| 4769 }else |
| 4770 |
| 4771 /* .session list |
| 4772 ** List all currently open sessions |
| 4773 */ |
| 4774 if( strcmp(azCmd[0],"list")==0 ){ |
| 4775 for(i=0; i<p->nSession; i++){ |
| 4776 utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName); |
| 4777 } |
| 4778 }else |
| 4779 |
| 4780 /* .session open DB NAME |
| 4781 ** Open a new session called NAME on the attached database DB. |
| 4782 ** DB is normally "main". |
| 4783 */ |
| 4784 if( strcmp(azCmd[0],"open")==0 ){ |
| 4785 char *zName; |
| 4786 if( nCmd!=3 ) goto session_syntax_error; |
| 4787 zName = azCmd[2]; |
| 4788 if( zName[0]==0 ) goto session_syntax_error; |
| 4789 for(i=0; i<p->nSession; i++){ |
| 4790 if( strcmp(p->aSession[i].zName,zName)==0 ){ |
| 4791 utf8_printf(stderr, "Session \"%s\" already exists\n", zName); |
| 4792 goto meta_command_exit; |
| 4793 } |
| 4794 } |
| 4795 if( p->nSession>=ArraySize(p->aSession) ){ |
| 4796 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession)); |
| 4797 goto meta_command_exit; |
| 4798 } |
| 4799 pSession = &p->aSession[p->nSession]; |
| 4800 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); |
| 4801 if( rc ){ |
| 4802 raw_printf(stderr, "Cannot open session: error code=%d\n", rc); |
| 4803 rc = 0; |
| 4804 goto meta_command_exit; |
| 4805 } |
| 4806 pSession->nFilter = 0; |
| 4807 sqlite3session_table_filter(pSession->p, session_filter, pSession); |
| 4808 p->nSession++; |
| 4809 pSession->zName = sqlite3_mprintf("%s", zName); |
| 4810 }else |
| 4811 /* If no command name matches, show a syntax error */ |
| 4812 session_syntax_error: |
| 4813 session_help(p); |
| 4814 }else |
| 4815 #endif |
3710 | 4816 |
3711 #ifdef SQLITE_DEBUG | 4817 #ifdef SQLITE_DEBUG |
3712 /* Undocumented commands for internal testing. Subject to change | 4818 /* Undocumented commands for internal testing. Subject to change |
3713 ** without notice. */ | 4819 ** without notice. */ |
3714 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ | 4820 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ |
3715 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ | 4821 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ |
3716 int i, v; | 4822 int i, v; |
3717 for(i=1; i<nArg; i++){ | 4823 for(i=1; i<nArg; i++){ |
3718 v = booleanValue(azArg[i]); | 4824 v = booleanValue(azArg[i]); |
3719 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); | 4825 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3760 for(i=2; i<nArg; i++){ | 4866 for(i=2; i<nArg; i++){ |
3761 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"", | 4867 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"", |
3762 zCmd, azArg[i]); | 4868 zCmd, azArg[i]); |
3763 } | 4869 } |
3764 x = system(zCmd); | 4870 x = system(zCmd); |
3765 sqlite3_free(zCmd); | 4871 sqlite3_free(zCmd); |
3766 if( x ) raw_printf(stderr, "System command returns %d\n", x); | 4872 if( x ) raw_printf(stderr, "System command returns %d\n", x); |
3767 }else | 4873 }else |
3768 | 4874 |
3769 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ | 4875 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ |
| 4876 static const char *azBool[] = { "off", "on", "full", "unk" }; |
3770 int i; | 4877 int i; |
3771 if( nArg!=1 ){ | 4878 if( nArg!=1 ){ |
3772 raw_printf(stderr, "Usage: .show\n"); | 4879 raw_printf(stderr, "Usage: .show\n"); |
3773 rc = 1; | 4880 rc = 1; |
3774 goto meta_command_exit; | 4881 goto meta_command_exit; |
3775 } | 4882 } |
3776 utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off"); | 4883 utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]); |
3777 utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off"); | 4884 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); |
3778 utf8_printf(p->out,"%9.9s: %s\n","explain",p->normalMode.valid?"on":"off"); | 4885 utf8_printf(p->out, "%12.12s: %s\n","explain", |
3779 utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); | 4886 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); |
| 4887 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); |
3780 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); | 4888 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); |
3781 utf8_printf(p->out, "%12.12s: ", "nullvalue"); | 4889 utf8_printf(p->out, "%12.12s: ", "nullvalue"); |
3782 output_c_string(p->out, p->nullValue); | 4890 output_c_string(p->out, p->nullValue); |
3783 raw_printf(p->out, "\n"); | 4891 raw_printf(p->out, "\n"); |
3784 utf8_printf(p->out,"%12.12s: %s\n","output", | 4892 utf8_printf(p->out,"%12.12s: %s\n","output", |
3785 strlen30(p->outfile) ? p->outfile : "stdout"); | 4893 strlen30(p->outfile) ? p->outfile : "stdout"); |
3786 utf8_printf(p->out,"%12.12s: ", "colseparator"); | 4894 utf8_printf(p->out,"%12.12s: ", "colseparator"); |
3787 output_c_string(p->out, p->colSeparator); | 4895 output_c_string(p->out, p->colSeparator); |
3788 raw_printf(p->out, "\n"); | 4896 raw_printf(p->out, "\n"); |
3789 utf8_printf(p->out,"%12.12s: ", "rowseparator"); | 4897 utf8_printf(p->out,"%12.12s: ", "rowseparator"); |
3790 output_c_string(p->out, p->rowSeparator); | 4898 output_c_string(p->out, p->rowSeparator); |
3791 raw_printf(p->out, "\n"); | 4899 raw_printf(p->out, "\n"); |
3792 utf8_printf(p->out, "%12.12s: %s\n","stats", p->statsOn ? "on" : "off"); | 4900 utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]); |
3793 utf8_printf(p->out, "%12.12s: ", "width"); | 4901 utf8_printf(p->out, "%12.12s: ", "width"); |
3794 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { | 4902 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { |
3795 raw_printf(p->out, "%d ", p->colWidth[i]); | 4903 raw_printf(p->out, "%d ", p->colWidth[i]); |
3796 } | 4904 } |
3797 raw_printf(p->out, "\n"); | 4905 raw_printf(p->out, "\n"); |
| 4906 utf8_printf(p->out, "%12.12s: %s\n", "filename", |
| 4907 p->zDbFilename ? p->zDbFilename : ""); |
3798 }else | 4908 }else |
3799 | 4909 |
3800 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ | 4910 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ |
3801 if( nArg==2 ){ | 4911 if( nArg==2 ){ |
3802 p->statsOn = booleanValue(azArg[1]); | 4912 p->statsOn = booleanValue(azArg[1]); |
| 4913 }else if( nArg==1 ){ |
| 4914 display_stats(p->db, p, 0); |
3803 }else{ | 4915 }else{ |
3804 raw_printf(stderr, "Usage: .stats on|off\n"); | 4916 raw_printf(stderr, "Usage: .stats ?on|off?\n"); |
3805 rc = 1; | 4917 rc = 1; |
3806 } | 4918 } |
3807 }else | 4919 }else |
3808 | 4920 |
3809 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ | 4921 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0) |
| 4922 || (c=='i' && (strncmp(azArg[0], "indices", n)==0 |
| 4923 || strncmp(azArg[0], "indexes", n)==0) ) |
| 4924 ){ |
3810 sqlite3_stmt *pStmt; | 4925 sqlite3_stmt *pStmt; |
3811 char **azResult; | 4926 char **azResult; |
3812 int nRow, nAlloc; | 4927 int nRow, nAlloc; |
3813 char *zSql = 0; | 4928 char *zSql = 0; |
3814 int ii; | 4929 int ii; |
3815 open_db(p, 0); | 4930 open_db(p, 0); |
3816 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); | 4931 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); |
3817 if( rc ) return shellDatabaseError(p->db); | 4932 if( rc ) return shellDatabaseError(p->db); |
3818 | 4933 |
3819 /* Create an SQL statement to query for the list of tables in the | 4934 /* 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 | 4935 ** main and all attached databases where the table name matches the |
3821 ** LIKE pattern bound to variable "?1". */ | 4936 ** LIKE pattern bound to variable "?1". */ |
3822 zSql = sqlite3_mprintf( | 4937 if( c=='t' ){ |
3823 "SELECT name FROM sqlite_master" | 4938 zSql = sqlite3_mprintf( |
3824 " WHERE type IN ('table','view')" | 4939 "SELECT name FROM sqlite_master" |
3825 " AND name NOT LIKE 'sqlite_%%'" | 4940 " WHERE type IN ('table','view')" |
3826 " AND name LIKE ?1"); | 4941 " AND name NOT LIKE 'sqlite_%%'" |
3827 while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){ | 4942 " AND name LIKE ?1"); |
| 4943 }else if( nArg>2 ){ |
| 4944 /* It is an historical accident that the .indexes command shows an error |
| 4945 ** when called with the wrong number of arguments whereas the .tables |
| 4946 ** command does not. */ |
| 4947 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); |
| 4948 rc = 1; |
| 4949 goto meta_command_exit; |
| 4950 }else{ |
| 4951 zSql = sqlite3_mprintf( |
| 4952 "SELECT name FROM sqlite_master" |
| 4953 " WHERE type='index'" |
| 4954 " AND tbl_name LIKE ?1"); |
| 4955 } |
| 4956 for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){ |
3828 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); | 4957 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); |
3829 if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; | 4958 if( zDbName==0 || ii==0 ) continue; |
3830 if( strcmp(zDbName,"temp")==0 ){ | 4959 if( c=='t' ){ |
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( | 4960 zSql = sqlite3_mprintf( |
3839 "%z UNION ALL " | 4961 "%z UNION ALL " |
3840 "SELECT '%q.' || name FROM \"%w\".sqlite_master" | 4962 "SELECT '%q.' || name FROM \"%w\".sqlite_master" |
3841 " WHERE type IN ('table','view')" | 4963 " WHERE type IN ('table','view')" |
3842 " AND name NOT LIKE 'sqlite_%%'" | 4964 " AND name NOT LIKE 'sqlite_%%'" |
3843 " AND name LIKE ?1", zSql, zDbName, zDbName); | 4965 " AND name LIKE ?1", zSql, zDbName, zDbName); |
| 4966 }else{ |
| 4967 zSql = sqlite3_mprintf( |
| 4968 "%z UNION ALL " |
| 4969 "SELECT '%q.' || name FROM \"%w\".sqlite_master" |
| 4970 " WHERE type='index'" |
| 4971 " AND tbl_name LIKE ?1", zSql, zDbName, zDbName); |
3844 } | 4972 } |
3845 } | 4973 } |
3846 rc = sqlite3_finalize(pStmt); | 4974 rc = sqlite3_finalize(pStmt); |
3847 if( zSql && rc==SQLITE_OK ){ | 4975 if( zSql && rc==SQLITE_OK ){ |
3848 zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); | 4976 zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); |
3849 if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); | 4977 if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); |
3850 } | 4978 } |
3851 sqlite3_free(zSql); | 4979 sqlite3_free(zSql); |
3852 if( !zSql ) return shellNomemError(); | 4980 if( !zSql ) return shellNomemError(); |
3853 if( rc ) return shellDatabaseError(p->db); | 4981 if( rc ) return shellDatabaseError(p->db); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 azResult[j] ? azResult[j]:""); | 5031 azResult[j] ? azResult[j]:""); |
3904 } | 5032 } |
3905 raw_printf(p->out, "\n"); | 5033 raw_printf(p->out, "\n"); |
3906 } | 5034 } |
3907 } | 5035 } |
3908 | 5036 |
3909 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); | 5037 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); |
3910 sqlite3_free(azResult); | 5038 sqlite3_free(azResult); |
3911 }else | 5039 }else |
3912 | 5040 |
| 5041 /* Begin redirecting output to the file "testcase-out.txt" */ |
| 5042 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ |
| 5043 output_reset(p); |
| 5044 p->out = output_file_open("testcase-out.txt"); |
| 5045 if( p->out==0 ){ |
| 5046 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); |
| 5047 } |
| 5048 if( nArg>=2 ){ |
| 5049 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); |
| 5050 }else{ |
| 5051 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); |
| 5052 } |
| 5053 }else |
| 5054 |
| 5055 #ifndef SQLITE_UNTESTABLE |
3913 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ | 5056 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ |
3914 static const struct { | 5057 static const struct { |
3915 const char *zCtrlName; /* Name of a test-control option */ | 5058 const char *zCtrlName; /* Name of a test-control option */ |
3916 int ctrlCode; /* Integer code for that option */ | 5059 int ctrlCode; /* Integer code for that option */ |
3917 } aCtrl[] = { | 5060 } aCtrl[] = { |
3918 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, | 5061 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, |
3919 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, | 5062 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, |
3920 { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, | 5063 { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, |
3921 { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, | 5064 { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, |
3922 { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, | 5065 { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, |
(...skipping 29 matching lines...) Expand all Loading... |
3952 } | 5095 } |
3953 } | 5096 } |
3954 if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); | 5097 if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); |
3955 if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){ | 5098 if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){ |
3956 utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); | 5099 utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); |
3957 }else{ | 5100 }else{ |
3958 switch(testctrl){ | 5101 switch(testctrl){ |
3959 | 5102 |
3960 /* sqlite3_test_control(int, db, int) */ | 5103 /* sqlite3_test_control(int, db, int) */ |
3961 case SQLITE_TESTCTRL_OPTIMIZATIONS: | 5104 case SQLITE_TESTCTRL_OPTIMIZATIONS: |
3962 case SQLITE_TESTCTRL_RESERVE: | 5105 case SQLITE_TESTCTRL_RESERVE: |
3963 if( nArg==3 ){ | 5106 if( nArg==3 ){ |
3964 int opt = (int)strtol(azArg[2], 0, 0); | 5107 int opt = (int)strtol(azArg[2], 0, 0); |
3965 rc2 = sqlite3_test_control(testctrl, p->db, opt); | 5108 rc2 = sqlite3_test_control(testctrl, p->db, opt); |
3966 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5109 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
3967 } else { | 5110 } else { |
3968 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", | 5111 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", |
3969 azArg[1]); | 5112 azArg[1]); |
3970 } | 5113 } |
3971 break; | 5114 break; |
3972 | 5115 |
3973 /* sqlite3_test_control(int) */ | 5116 /* sqlite3_test_control(int) */ |
3974 case SQLITE_TESTCTRL_PRNG_SAVE: | 5117 case SQLITE_TESTCTRL_PRNG_SAVE: |
3975 case SQLITE_TESTCTRL_PRNG_RESTORE: | 5118 case SQLITE_TESTCTRL_PRNG_RESTORE: |
3976 case SQLITE_TESTCTRL_PRNG_RESET: | 5119 case SQLITE_TESTCTRL_PRNG_RESET: |
3977 case SQLITE_TESTCTRL_BYTEORDER: | 5120 case SQLITE_TESTCTRL_BYTEORDER: |
3978 if( nArg==2 ){ | 5121 if( nArg==2 ){ |
3979 rc2 = sqlite3_test_control(testctrl); | 5122 rc2 = sqlite3_test_control(testctrl); |
3980 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5123 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
3981 } else { | 5124 } else { |
3982 utf8_printf(stderr,"Error: testctrl %s takes no options\n", | 5125 utf8_printf(stderr,"Error: testctrl %s takes no options\n", |
3983 azArg[1]); | 5126 azArg[1]); |
3984 } | 5127 } |
3985 break; | 5128 break; |
3986 | 5129 |
3987 /* sqlite3_test_control(int, uint) */ | 5130 /* sqlite3_test_control(int, uint) */ |
3988 case SQLITE_TESTCTRL_PENDING_BYTE: | 5131 case SQLITE_TESTCTRL_PENDING_BYTE: |
3989 if( nArg==3 ){ | 5132 if( nArg==3 ){ |
3990 unsigned int opt = (unsigned int)integerValue(azArg[2]); | 5133 unsigned int opt = (unsigned int)integerValue(azArg[2]); |
3991 rc2 = sqlite3_test_control(testctrl, opt); | 5134 rc2 = sqlite3_test_control(testctrl, opt); |
3992 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5135 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
3993 } else { | 5136 } else { |
3994 utf8_printf(stderr,"Error: testctrl %s takes a single unsigned" | 5137 utf8_printf(stderr,"Error: testctrl %s takes a single unsigned" |
3995 " int option\n", azArg[1]); | 5138 " int option\n", azArg[1]); |
3996 } | 5139 } |
3997 break; | 5140 break; |
3998 | 5141 |
3999 /* sqlite3_test_control(int, int) */ | 5142 /* sqlite3_test_control(int, int) */ |
4000 case SQLITE_TESTCTRL_ASSERT: | 5143 case SQLITE_TESTCTRL_ASSERT: |
4001 case SQLITE_TESTCTRL_ALWAYS: | 5144 case SQLITE_TESTCTRL_ALWAYS: |
4002 case SQLITE_TESTCTRL_NEVER_CORRUPT: | 5145 case SQLITE_TESTCTRL_NEVER_CORRUPT: |
4003 if( nArg==3 ){ | 5146 if( nArg==3 ){ |
4004 int opt = booleanValue(azArg[2]); | 5147 int opt = booleanValue(azArg[2]); |
4005 rc2 = sqlite3_test_control(testctrl, opt); | 5148 rc2 = sqlite3_test_control(testctrl, opt); |
4006 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5149 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
4007 } else { | 5150 } else { |
4008 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", | 5151 utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", |
4009 azArg[1]); | 5152 azArg[1]); |
4010 } | 5153 } |
4011 break; | 5154 break; |
4012 | 5155 |
4013 /* sqlite3_test_control(int, char *) */ | 5156 /* sqlite3_test_control(int, char *) */ |
4014 #ifdef SQLITE_N_KEYWORD | 5157 #ifdef SQLITE_N_KEYWORD |
4015 case SQLITE_TESTCTRL_ISKEYWORD: | 5158 case SQLITE_TESTCTRL_ISKEYWORD: |
4016 if( nArg==3 ){ | 5159 if( nArg==3 ){ |
4017 const char *opt = azArg[2]; | 5160 const char *opt = azArg[2]; |
4018 rc2 = sqlite3_test_control(testctrl, opt); | 5161 rc2 = sqlite3_test_control(testctrl, opt); |
4019 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5162 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
4020 } else { | 5163 } else { |
4021 utf8_printf(stderr, | 5164 utf8_printf(stderr, |
4022 "Error: testctrl %s takes a single char * option\n", | 5165 "Error: testctrl %s takes a single char * option\n", |
4023 azArg[1]); | 5166 azArg[1]); |
4024 } | 5167 } |
4025 break; | 5168 break; |
4026 #endif | 5169 #endif |
4027 | 5170 |
4028 case SQLITE_TESTCTRL_IMPOSTER: | 5171 case SQLITE_TESTCTRL_IMPOSTER: |
4029 if( nArg==5 ){ | 5172 if( nArg==5 ){ |
4030 rc2 = sqlite3_test_control(testctrl, p->db, | 5173 rc2 = sqlite3_test_control(testctrl, p->db, |
4031 azArg[2], | 5174 azArg[2], |
4032 integerValue(azArg[3]), | 5175 integerValue(azArg[3]), |
4033 integerValue(azArg[4])); | 5176 integerValue(azArg[4])); |
4034 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); | 5177 raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); |
4035 }else{ | 5178 }else{ |
4036 raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); | 5179 raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); |
4037 } | 5180 } |
4038 break; | 5181 break; |
4039 | 5182 |
4040 case SQLITE_TESTCTRL_BITVEC_TEST: | 5183 case SQLITE_TESTCTRL_BITVEC_TEST: |
4041 case SQLITE_TESTCTRL_FAULT_INSTALL: | 5184 case SQLITE_TESTCTRL_FAULT_INSTALL: |
4042 case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: | 5185 case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: |
4043 case SQLITE_TESTCTRL_SCRATCHMALLOC: | 5186 case SQLITE_TESTCTRL_SCRATCHMALLOC: |
4044 default: | 5187 default: |
4045 utf8_printf(stderr, | 5188 utf8_printf(stderr, |
4046 "Error: CLI support for testctrl %s not implemented\n", | 5189 "Error: CLI support for testctrl %s not implemented\n", |
4047 azArg[1]); | 5190 azArg[1]); |
4048 break; | 5191 break; |
4049 } | 5192 } |
4050 } | 5193 } |
4051 }else | 5194 }else |
4052 | 5195 |
4053 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ | 5196 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ |
4054 open_db(p, 0); | 5197 open_db(p, 0); |
4055 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); | 5198 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); |
4056 }else | 5199 }else |
4057 | 5200 |
4058 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ | 5201 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ |
4059 if( nArg==2 ){ | 5202 if( nArg==2 ){ |
4060 enableTimer = booleanValue(azArg[1]); | 5203 enableTimer = booleanValue(azArg[1]); |
4061 if( enableTimer && !HAS_TIMER ){ | 5204 if( enableTimer && !HAS_TIMER ){ |
4062 raw_printf(stderr, "Error: timer not available on this system.\n"); | 5205 raw_printf(stderr, "Error: timer not available on this system.\n"); |
4063 enableTimer = 0; | 5206 enableTimer = 0; |
4064 } | 5207 } |
4065 }else{ | 5208 }else{ |
4066 raw_printf(stderr, "Usage: .timer on|off\n"); | 5209 raw_printf(stderr, "Usage: .timer on|off\n"); |
4067 rc = 1; | 5210 rc = 1; |
4068 } | 5211 } |
4069 }else | 5212 }else |
4070 | 5213 |
4071 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ | 5214 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ |
4072 open_db(p, 0); | 5215 open_db(p, 0); |
4073 if( nArg!=2 ){ | 5216 if( nArg!=2 ){ |
4074 raw_printf(stderr, "Usage: .trace FILE|off\n"); | 5217 raw_printf(stderr, "Usage: .trace FILE|off\n"); |
4075 rc = 1; | 5218 rc = 1; |
4076 goto meta_command_exit; | 5219 goto meta_command_exit; |
4077 } | 5220 } |
4078 output_file_close(p->traceOut); | 5221 output_file_close(p->traceOut); |
4079 p->traceOut = output_file_open(azArg[1]); | 5222 p->traceOut = output_file_open(azArg[1]); |
4080 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) | 5223 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) |
4081 if( p->traceOut==0 ){ | 5224 if( p->traceOut==0 ){ |
4082 sqlite3_trace(p->db, 0, 0); | 5225 sqlite3_trace_v2(p->db, 0, 0, 0); |
4083 }else{ | 5226 }else{ |
4084 sqlite3_trace(p->db, sql_trace_callback, p->traceOut); | 5227 sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut)
; |
4085 } | 5228 } |
4086 #endif | 5229 #endif |
4087 }else | 5230 }else |
| 5231 #endif /* !defined(SQLITE_UNTESTABLE) */ |
4088 | 5232 |
4089 #if SQLITE_USER_AUTHENTICATION | 5233 #if SQLITE_USER_AUTHENTICATION |
4090 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ | 5234 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ |
4091 if( nArg<2 ){ | 5235 if( nArg<2 ){ |
4092 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); | 5236 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); |
4093 rc = 1; | 5237 rc = 1; |
4094 goto meta_command_exit; | 5238 goto meta_command_exit; |
4095 } | 5239 } |
4096 open_db(p, 0); | 5240 open_db(p, 0); |
4097 if( strcmp(azArg[1],"login")==0 ){ | 5241 if( strcmp(azArg[1],"login")==0 ){ |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4140 } | 5284 } |
4141 rc = sqlite3_user_delete(p->db, azArg[2]); | 5285 rc = sqlite3_user_delete(p->db, azArg[2]); |
4142 if( rc ){ | 5286 if( rc ){ |
4143 raw_printf(stderr, "User-Delete failed: %d\n", rc); | 5287 raw_printf(stderr, "User-Delete failed: %d\n", rc); |
4144 rc = 1; | 5288 rc = 1; |
4145 } | 5289 } |
4146 }else{ | 5290 }else{ |
4147 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); | 5291 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); |
4148 rc = 1; | 5292 rc = 1; |
4149 goto meta_command_exit; | 5293 goto meta_command_exit; |
4150 } | 5294 } |
4151 }else | 5295 }else |
4152 #endif /* SQLITE_USER_AUTHENTICATION */ | 5296 #endif /* SQLITE_USER_AUTHENTICATION */ |
4153 | 5297 |
4154 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ | 5298 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ |
4155 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, | 5299 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, |
4156 sqlite3_libversion(), sqlite3_sourceid()); | 5300 sqlite3_libversion(), sqlite3_sourceid()); |
4157 }else | 5301 }else |
4158 | 5302 |
4159 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ | 5303 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ |
4160 const char *zDbName = nArg==2 ? azArg[1] : "main"; | 5304 const char *zDbName = nArg==2 ? azArg[1] : "main"; |
4161 sqlite3_vfs *pVfs; | 5305 sqlite3_vfs *pVfs = 0; |
4162 if( p->db ){ | 5306 if( p->db ){ |
4163 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); | 5307 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); |
4164 if( pVfs ){ | 5308 if( pVfs ){ |
4165 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); | 5309 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); |
4166 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); | 5310 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); |
4167 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); | 5311 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); |
4168 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); | 5312 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); |
4169 } | 5313 } |
4170 } | 5314 } |
4171 }else | 5315 }else |
4172 | 5316 |
| 5317 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){ |
| 5318 sqlite3_vfs *pVfs; |
| 5319 sqlite3_vfs *pCurrent = 0; |
| 5320 if( p->db ){ |
| 5321 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent); |
| 5322 } |
| 5323 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ |
| 5324 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, |
| 5325 pVfs==pCurrent ? " <--- CURRENT" : ""); |
| 5326 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); |
| 5327 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); |
| 5328 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); |
| 5329 if( pVfs->pNext ){ |
| 5330 raw_printf(p->out, "-----------------------------------\n"); |
| 5331 } |
| 5332 } |
| 5333 }else |
| 5334 |
4173 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ | 5335 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ |
4174 const char *zDbName = nArg==2 ? azArg[1] : "main"; | 5336 const char *zDbName = nArg==2 ? azArg[1] : "main"; |
4175 char *zVfsName = 0; | 5337 char *zVfsName = 0; |
4176 if( p->db ){ | 5338 if( p->db ){ |
4177 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); | 5339 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); |
4178 if( zVfsName ){ | 5340 if( zVfsName ){ |
4179 utf8_printf(p->out, "%s\n", zVfsName); | 5341 utf8_printf(p->out, "%s\n", zVfsName); |
4180 sqlite3_free(zVfsName); | 5342 sqlite3_free(zVfsName); |
4181 } | 5343 } |
4182 } | 5344 } |
4183 }else | 5345 }else |
4184 | 5346 |
4185 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) | 5347 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) |
4186 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ | 5348 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ |
4187 extern int sqlite3WhereTrace; | |
4188 sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; | 5349 sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; |
4189 }else | 5350 }else |
4190 #endif | 5351 #endif |
4191 | 5352 |
4192 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ | 5353 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ |
4193 int j; | 5354 int j; |
4194 assert( nArg<=ArraySize(azArg) ); | 5355 assert( nArg<=ArraySize(azArg) ); |
4195 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ | 5356 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ |
4196 p->colWidth[j-1] = (int)integerValue(azArg[j]); | 5357 p->colWidth[j-1] = (int)integerValue(azArg[j]); |
4197 } | 5358 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4270 int rc; | 5431 int rc; |
4271 if( zSql==0 ) return 1; | 5432 if( zSql==0 ) return 1; |
4272 zSql[nSql] = ';'; | 5433 zSql[nSql] = ';'; |
4273 zSql[nSql+1] = 0; | 5434 zSql[nSql+1] = 0; |
4274 rc = sqlite3_complete(zSql); | 5435 rc = sqlite3_complete(zSql); |
4275 zSql[nSql] = 0; | 5436 zSql[nSql] = 0; |
4276 return rc; | 5437 return rc; |
4277 } | 5438 } |
4278 | 5439 |
4279 /* | 5440 /* |
| 5441 ** Run a single line of SQL |
| 5442 */ |
| 5443 static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ |
| 5444 int rc; |
| 5445 char *zErrMsg = 0; |
| 5446 |
| 5447 open_db(p, 0); |
| 5448 if( p->backslashOn ) resolve_backslashes(zSql); |
| 5449 BEGIN_TIMER; |
| 5450 rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); |
| 5451 END_TIMER; |
| 5452 if( rc || zErrMsg ){ |
| 5453 char zPrefix[100]; |
| 5454 if( in!=0 || !stdin_is_interactive ){ |
| 5455 sqlite3_snprintf(sizeof(zPrefix), zPrefix, |
| 5456 "Error: near line %d:", startline); |
| 5457 }else{ |
| 5458 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); |
| 5459 } |
| 5460 if( zErrMsg!=0 ){ |
| 5461 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); |
| 5462 sqlite3_free(zErrMsg); |
| 5463 zErrMsg = 0; |
| 5464 }else{ |
| 5465 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); |
| 5466 } |
| 5467 return 1; |
| 5468 }else if( p->countChanges ){ |
| 5469 raw_printf(p->out, "changes: %3d total_changes: %d\n", |
| 5470 sqlite3_changes(p->db), sqlite3_total_changes(p->db)); |
| 5471 } |
| 5472 return 0; |
| 5473 } |
| 5474 |
| 5475 |
| 5476 /* |
4280 ** Read input from *in and process it. If *in==0 then input | 5477 ** Read input from *in and process it. If *in==0 then input |
4281 ** is interactive - the user is typing it it. Otherwise, input | 5478 ** is interactive - the user is typing it it. Otherwise, input |
4282 ** is coming from a file or device. A prompt is issued and history | 5479 ** 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 | 5480 ** is saved only if input is interactive. An interrupt signal will |
4284 ** cause this routine to exit immediately, unless input is interactive. | 5481 ** cause this routine to exit immediately, unless input is interactive. |
4285 ** | 5482 ** |
4286 ** Return the number of errors. | 5483 ** Return the number of errors. |
4287 */ | 5484 */ |
4288 static int process_input(ShellState *p, FILE *in){ | 5485 static int process_input(ShellState *p, FILE *in){ |
4289 char *zLine = 0; /* A single input line */ | 5486 char *zLine = 0; /* A single input line */ |
4290 char *zSql = 0; /* Accumulated SQL text */ | 5487 char *zSql = 0; /* Accumulated SQL text */ |
4291 int nLine; /* Length of current line */ | 5488 int nLine; /* Length of current line */ |
4292 int nSql = 0; /* Bytes of zSql[] used */ | 5489 int nSql = 0; /* Bytes of zSql[] used */ |
4293 int nAlloc = 0; /* Allocated zSql[] space */ | 5490 int nAlloc = 0; /* Allocated zSql[] space */ |
4294 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ | 5491 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ |
4295 char *zErrMsg; /* Error message returned */ | |
4296 int rc; /* Error code */ | 5492 int rc; /* Error code */ |
4297 int errCnt = 0; /* Number of errors seen */ | 5493 int errCnt = 0; /* Number of errors seen */ |
4298 int lineno = 0; /* Current line number */ | 5494 int lineno = 0; /* Current line number */ |
4299 int startline = 0; /* Line number for start of current input */ | 5495 int startline = 0; /* Line number for start of current input */ |
4300 | 5496 |
4301 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ | 5497 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ |
4302 fflush(p->out); | 5498 fflush(p->out); |
4303 zLine = one_input_line(in, zLine, nSql>0); | 5499 zLine = one_input_line(in, zLine, nSql>0); |
4304 if( zLine==0 ){ | 5500 if( zLine==0 ){ |
4305 /* End of input */ | 5501 /* End of input */ |
4306 if( stdin_is_interactive ) printf("\n"); | 5502 if( in==0 && stdin_is_interactive ) printf("\n"); |
4307 break; | 5503 break; |
4308 } | 5504 } |
4309 if( seenInterrupt ){ | 5505 if( seenInterrupt ){ |
4310 if( in!=0 ) break; | 5506 if( in!=0 ) break; |
4311 seenInterrupt = 0; | 5507 seenInterrupt = 0; |
4312 } | 5508 } |
4313 lineno++; | 5509 lineno++; |
4314 if( nSql==0 && _all_whitespace(zLine) ){ | 5510 if( nSql==0 && _all_whitespace(zLine) ){ |
4315 if( p->echoOn ) printf("%s\n", zLine); | 5511 if( p->echoOn ) printf("%s\n", zLine); |
4316 continue; | 5512 continue; |
(...skipping 28 matching lines...) Expand all Loading... |
4345 memcpy(zSql, zLine+i, nLine+1-i); | 5541 memcpy(zSql, zLine+i, nLine+1-i); |
4346 startline = lineno; | 5542 startline = lineno; |
4347 nSql = nLine-i; | 5543 nSql = nLine-i; |
4348 }else{ | 5544 }else{ |
4349 zSql[nSql++] = '\n'; | 5545 zSql[nSql++] = '\n'; |
4350 memcpy(zSql+nSql, zLine, nLine+1); | 5546 memcpy(zSql+nSql, zLine, nLine+1); |
4351 nSql += nLine; | 5547 nSql += nLine; |
4352 } | 5548 } |
4353 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) | 5549 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) |
4354 && sqlite3_complete(zSql) ){ | 5550 && sqlite3_complete(zSql) ){ |
4355 p->cnt = 0; | 5551 errCnt += runOneSqlLine(p, zSql, in, startline); |
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; | 5552 nSql = 0; |
4382 if( p->outCount ){ | 5553 if( p->outCount ){ |
4383 output_reset(p); | 5554 output_reset(p); |
4384 p->outCount = 0; | 5555 p->outCount = 0; |
4385 } | 5556 } |
4386 }else if( nSql && _all_whitespace(zSql) ){ | 5557 }else if( nSql && _all_whitespace(zSql) ){ |
4387 if( p->echoOn ) printf("%s\n", zSql); | 5558 if( p->echoOn ) printf("%s\n", zSql); |
4388 nSql = 0; | 5559 nSql = 0; |
4389 } | 5560 } |
4390 } | 5561 } |
4391 if( nSql ){ | 5562 if( nSql && !_all_whitespace(zSql) ){ |
4392 if( !_all_whitespace(zSql) ){ | 5563 runOneSqlLine(p, zSql, in, startline); |
4393 utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql); | |
4394 errCnt++; | |
4395 } | |
4396 } | 5564 } |
4397 free(zSql); | 5565 free(zSql); |
4398 free(zLine); | 5566 free(zLine); |
4399 return errCnt>0; | 5567 return errCnt>0; |
4400 } | 5568 } |
4401 | 5569 |
4402 /* | 5570 /* |
4403 ** Return a pathname which is the user's home directory. A | 5571 ** Return a pathname which is the user's home directory. A |
4404 ** 0 return indicates an error of some kind. | 5572 ** 0 return indicates an error of some kind. |
4405 */ | 5573 */ |
4406 static char *find_home_dir(void){ | 5574 static char *find_home_dir(int clearFlag){ |
4407 static char *home_dir = NULL; | 5575 static char *home_dir = NULL; |
| 5576 if( clearFlag ){ |
| 5577 free(home_dir); |
| 5578 home_dir = 0; |
| 5579 return 0; |
| 5580 } |
4408 if( home_dir ) return home_dir; | 5581 if( home_dir ) return home_dir; |
4409 | 5582 |
4410 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ | 5583 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ |
4411 && !defined(__RTP__) && !defined(_WRS_KERNEL) | 5584 && !defined(__RTP__) && !defined(_WRS_KERNEL) |
4412 { | 5585 { |
4413 struct passwd *pwent; | 5586 struct passwd *pwent; |
4414 uid_t uid = getuid(); | 5587 uid_t uid = getuid(); |
4415 if( (pwent=getpwuid(uid)) != NULL) { | 5588 if( (pwent=getpwuid(uid)) != NULL) { |
4416 home_dir = pwent->pw_dir; | 5589 home_dir = pwent->pw_dir; |
4417 } | 5590 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4472 static void process_sqliterc( | 5645 static void process_sqliterc( |
4473 ShellState *p, /* Configuration data */ | 5646 ShellState *p, /* Configuration data */ |
4474 const char *sqliterc_override /* Name of config file. NULL to use default */ | 5647 const char *sqliterc_override /* Name of config file. NULL to use default */ |
4475 ){ | 5648 ){ |
4476 char *home_dir = NULL; | 5649 char *home_dir = NULL; |
4477 const char *sqliterc = sqliterc_override; | 5650 const char *sqliterc = sqliterc_override; |
4478 char *zBuf = 0; | 5651 char *zBuf = 0; |
4479 FILE *in = NULL; | 5652 FILE *in = NULL; |
4480 | 5653 |
4481 if (sqliterc == NULL) { | 5654 if (sqliterc == NULL) { |
4482 home_dir = find_home_dir(); | 5655 home_dir = find_home_dir(0); |
4483 if( home_dir==0 ){ | 5656 if( home_dir==0 ){ |
4484 raw_printf(stderr, "-- warning: cannot find home directory;" | 5657 raw_printf(stderr, "-- warning: cannot find home directory;" |
4485 " cannot read ~/.sqliterc\n"); | 5658 " cannot read ~/.sqliterc\n"); |
4486 return; | 5659 return; |
4487 } | 5660 } |
4488 sqlite3_initialize(); | 5661 sqlite3_initialize(); |
4489 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); | 5662 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); |
4490 sqliterc = zBuf; | 5663 sqliterc = zBuf; |
4491 } | 5664 } |
4492 in = fopen(sqliterc,"rb"); | 5665 in = fopen(sqliterc,"rb"); |
4493 if( in ){ | 5666 if( in ){ |
4494 if( stdin_is_interactive ){ | 5667 if( stdin_is_interactive ){ |
4495 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); | 5668 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); |
4496 } | 5669 } |
4497 process_input(p,in); | 5670 process_input(p,in); |
4498 fclose(in); | 5671 fclose(in); |
4499 } | 5672 } |
4500 sqlite3_free(zBuf); | 5673 sqlite3_free(zBuf); |
4501 } | 5674 } |
4502 | 5675 |
4503 /* | 5676 /* |
4504 ** Show available command line options | 5677 ** Show available command line options |
4505 */ | 5678 */ |
4506 static const char zOptions[] = | 5679 static const char zOptions[] = |
4507 " -ascii set output mode to 'ascii'\n" | 5680 " -ascii set output mode to 'ascii'\n" |
4508 " -bail stop after hitting an error\n" | 5681 " -bail stop after hitting an error\n" |
4509 " -batch force batch I/O\n" | 5682 " -batch force batch I/O\n" |
4510 " -column set output mode to 'column'\n" | 5683 " -column set output mode to 'column'\n" |
4511 " -cmd COMMAND run \"COMMAND\" before reading stdin\n" | 5684 " -cmd COMMAND run \"COMMAND\" before reading stdin\n" |
4512 " -csv set output mode to 'csv'\n" | 5685 " -csv set output mode to 'csv'\n" |
4513 " -echo print commands before execution\n" | 5686 " -echo print commands before execution\n" |
4514 " -init FILENAME read/process named file\n" | 5687 " -init FILENAME read/process named file\n" |
4515 " -[no]header turn headers on or off\n" | 5688 " -[no]header turn headers on or off\n" |
4516 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) | 5689 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) |
(...skipping 16 matching lines...) Expand all Loading... |
4533 " -separator SEP set output column separator. Default: '|'\n" | 5706 " -separator SEP set output column separator. Default: '|'\n" |
4534 " -stats print memory stats before each finalize\n" | 5707 " -stats print memory stats before each finalize\n" |
4535 " -version show SQLite version\n" | 5708 " -version show SQLite version\n" |
4536 " -vfs NAME use NAME as the default VFS\n" | 5709 " -vfs NAME use NAME as the default VFS\n" |
4537 #ifdef SQLITE_ENABLE_VFSTRACE | 5710 #ifdef SQLITE_ENABLE_VFSTRACE |
4538 " -vfstrace enable tracing of all VFS calls\n" | 5711 " -vfstrace enable tracing of all VFS calls\n" |
4539 #endif | 5712 #endif |
4540 ; | 5713 ; |
4541 static void usage(int showDetail){ | 5714 static void usage(int showDetail){ |
4542 utf8_printf(stderr, | 5715 utf8_printf(stderr, |
4543 "Usage: %s [OPTIONS] FILENAME [SQL]\n" | 5716 "Usage: %s [OPTIONS] FILENAME [SQL]\n" |
4544 "FILENAME is the name of an SQLite database. A new database is created\n" | 5717 "FILENAME is the name of an SQLite database. A new database is created\n" |
4545 "if the file does not previously exist.\n", Argv0); | 5718 "if the file does not previously exist.\n", Argv0); |
4546 if( showDetail ){ | 5719 if( showDetail ){ |
4547 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); | 5720 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); |
4548 }else{ | 5721 }else{ |
4549 raw_printf(stderr, "Use the -help option for additional information\n"); | 5722 raw_printf(stderr, "Use the -help option for additional information\n"); |
4550 } | 5723 } |
4551 exit(1); | 5724 exit(1); |
4552 } | 5725 } |
4553 | 5726 |
4554 /* | 5727 /* |
4555 ** Initialize the state information in data | 5728 ** Initialize the state information in data |
4556 */ | 5729 */ |
4557 static void main_init(ShellState *data) { | 5730 static void main_init(ShellState *data) { |
4558 memset(data, 0, sizeof(*data)); | 5731 memset(data, 0, sizeof(*data)); |
4559 data->mode = MODE_List; | 5732 data->normalMode = data->cMode = data->mode = MODE_List; |
| 5733 data->autoExplain = 1; |
4560 memcpy(data->colSeparator,SEP_Column, 2); | 5734 memcpy(data->colSeparator,SEP_Column, 2); |
4561 memcpy(data->rowSeparator,SEP_Row, 2); | 5735 memcpy(data->rowSeparator,SEP_Row, 2); |
4562 data->showHeader = 0; | 5736 data->showHeader = 0; |
4563 data->shellFlgs = SHFLG_Lookaside; | 5737 data->shellFlgs = SHFLG_Lookaside; |
4564 sqlite3_config(SQLITE_CONFIG_URI, 1); | 5738 sqlite3_config(SQLITE_CONFIG_URI, 1); |
4565 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); | 5739 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); |
4566 sqlite3_config(SQLITE_CONFIG_MULTITHREAD); | 5740 sqlite3_config(SQLITE_CONFIG_MULTITHREAD); |
4567 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); | 5741 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); |
4568 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); | 5742 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); |
4569 } | 5743 } |
(...skipping 24 matching lines...) Expand all Loading... |
4594 */ | 5768 */ |
4595 static char *cmdline_option_value(int argc, char **argv, int i){ | 5769 static char *cmdline_option_value(int argc, char **argv, int i){ |
4596 if( i==argc ){ | 5770 if( i==argc ){ |
4597 utf8_printf(stderr, "%s: Error: missing argument to %s\n", | 5771 utf8_printf(stderr, "%s: Error: missing argument to %s\n", |
4598 argv[0], argv[argc-1]); | 5772 argv[0], argv[argc-1]); |
4599 exit(1); | 5773 exit(1); |
4600 } | 5774 } |
4601 return argv[i]; | 5775 return argv[i]; |
4602 } | 5776 } |
4603 | 5777 |
| 5778 #ifndef SQLITE_SHELL_IS_UTF8 |
| 5779 # if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) |
| 5780 # define SQLITE_SHELL_IS_UTF8 (0) |
| 5781 # else |
| 5782 # define SQLITE_SHELL_IS_UTF8 (1) |
| 5783 # endif |
| 5784 #endif |
| 5785 |
| 5786 #if SQLITE_SHELL_IS_UTF8 |
4604 int SQLITE_CDECL main(int argc, char **argv){ | 5787 int SQLITE_CDECL main(int argc, char **argv){ |
| 5788 #else |
| 5789 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ |
| 5790 char **argv; |
| 5791 #endif |
4605 char *zErrMsg = 0; | 5792 char *zErrMsg = 0; |
4606 ShellState data; | 5793 ShellState data; |
4607 const char *zInitFile = 0; | 5794 const char *zInitFile = 0; |
4608 int i; | 5795 int i; |
4609 int rc = 0; | 5796 int rc = 0; |
4610 int warnInmemoryDb = 0; | 5797 int warnInmemoryDb = 0; |
4611 int readStdin = 1; | 5798 int readStdin = 1; |
4612 int nCmd = 0; | 5799 int nCmd = 0; |
4613 char **azCmd = 0; | 5800 char **azCmd = 0; |
4614 | 5801 |
| 5802 setBinaryMode(stdin, 0); |
| 5803 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ |
| 5804 stdin_is_interactive = isatty(0); |
| 5805 stdout_is_console = isatty(1); |
| 5806 |
4615 #if USE_SYSTEM_SQLITE+0!=1 | 5807 #if USE_SYSTEM_SQLITE+0!=1 |
4616 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ | 5808 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ |
4617 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", | 5809 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", |
4618 sqlite3_sourceid(), SQLITE_SOURCE_ID); | 5810 sqlite3_sourceid(), SQLITE_SOURCE_ID); |
4619 exit(1); | 5811 exit(1); |
4620 } | 5812 } |
4621 #endif | 5813 #endif |
4622 setBinaryMode(stdin); | 5814 main_init(&data); |
4623 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ | 5815 #if !SQLITE_SHELL_IS_UTF8 |
| 5816 sqlite3_initialize(); |
| 5817 argv = sqlite3_malloc64(sizeof(argv[0])*argc); |
| 5818 if( argv==0 ){ |
| 5819 raw_printf(stderr, "out of memory\n"); |
| 5820 exit(1); |
| 5821 } |
| 5822 for(i=0; i<argc; i++){ |
| 5823 argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]); |
| 5824 if( argv[i]==0 ){ |
| 5825 raw_printf(stderr, "out of memory\n"); |
| 5826 exit(1); |
| 5827 } |
| 5828 } |
| 5829 #endif |
| 5830 assert( argc>=1 && argv && argv[0] ); |
4624 Argv0 = argv[0]; | 5831 Argv0 = argv[0]; |
4625 main_init(&data); | |
4626 stdin_is_interactive = isatty(0); | |
4627 stdout_is_console = isatty(1); | |
4628 | 5832 |
4629 /* Make sure we have a valid signal handler early, before anything | 5833 /* Make sure we have a valid signal handler early, before anything |
4630 ** else is done. | 5834 ** else is done. |
4631 */ | 5835 */ |
4632 #ifdef SIGINT | 5836 #ifdef SIGINT |
4633 signal(SIGINT, interrupt_handler); | 5837 signal(SIGINT, interrupt_handler); |
4634 #endif | 5838 #endif |
4635 | 5839 |
4636 #ifdef SQLITE_SHELL_DBNAME_PROC | 5840 #ifdef SQLITE_SHELL_DBNAME_PROC |
4637 { | 5841 { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4683 if( strcmp(z,"-separator")==0 | 5887 if( strcmp(z,"-separator")==0 |
4684 || strcmp(z,"-nullvalue")==0 | 5888 || strcmp(z,"-nullvalue")==0 |
4685 || strcmp(z,"-newline")==0 | 5889 || strcmp(z,"-newline")==0 |
4686 || strcmp(z,"-cmd")==0 | 5890 || strcmp(z,"-cmd")==0 |
4687 ){ | 5891 ){ |
4688 (void)cmdline_option_value(argc, argv, ++i); | 5892 (void)cmdline_option_value(argc, argv, ++i); |
4689 }else if( strcmp(z,"-init")==0 ){ | 5893 }else if( strcmp(z,"-init")==0 ){ |
4690 zInitFile = cmdline_option_value(argc, argv, ++i); | 5894 zInitFile = cmdline_option_value(argc, argv, ++i); |
4691 }else if( strcmp(z,"-batch")==0 ){ | 5895 }else if( strcmp(z,"-batch")==0 ){ |
4692 /* Need to check for batch mode here to so we can avoid printing | 5896 /* Need to check for batch mode here to so we can avoid printing |
4693 ** informational messages (like from process_sqliterc) before | 5897 ** informational messages (like from process_sqliterc) before |
4694 ** we do the actual processing of arguments later in a second pass. | 5898 ** we do the actual processing of arguments later in a second pass. |
4695 */ | 5899 */ |
4696 stdin_is_interactive = 0; | 5900 stdin_is_interactive = 0; |
4697 }else if( strcmp(z,"-heap")==0 ){ | 5901 }else if( strcmp(z,"-heap")==0 ){ |
4698 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) | 5902 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) |
4699 const char *zSize; | 5903 const char *zSize; |
4700 sqlite3_int64 szHeap; | 5904 sqlite3_int64 szHeap; |
4701 | 5905 |
4702 zSize = cmdline_option_value(argc, argv, ++i); | 5906 zSize = cmdline_option_value(argc, argv, ++i); |
4703 szHeap = integerValue(zSize); | 5907 szHeap = integerValue(zSize); |
4704 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; | 5908 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; |
4705 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); | 5909 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); |
| 5910 #else |
| 5911 (void)cmdline_option_value(argc, argv, ++i); |
4706 #endif | 5912 #endif |
4707 }else if( strcmp(z,"-scratch")==0 ){ | 5913 }else if( strcmp(z,"-scratch")==0 ){ |
4708 int n, sz; | 5914 int n, sz; |
4709 sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); | 5915 sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); |
4710 if( sz>400000 ) sz = 400000; | 5916 if( sz>400000 ) sz = 400000; |
4711 if( sz<2500 ) sz = 2500; | 5917 if( sz<2500 ) sz = 2500; |
4712 n = (int)integerValue(cmdline_option_value(argc,argv,++i)); | 5918 n = (int)integerValue(cmdline_option_value(argc,argv,++i)); |
4713 if( n>10 ) n = 10; | 5919 if( n>10 ) n = 10; |
4714 if( n<1 ) n = 1; | 5920 if( n<1 ) n = 1; |
4715 sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n); | 5921 sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4824 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue, | 6030 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue, |
4825 "%s",cmdline_option_value(argc,argv,++i)); | 6031 "%s",cmdline_option_value(argc,argv,++i)); |
4826 }else if( strcmp(z,"-header")==0 ){ | 6032 }else if( strcmp(z,"-header")==0 ){ |
4827 data.showHeader = 1; | 6033 data.showHeader = 1; |
4828 }else if( strcmp(z,"-noheader")==0 ){ | 6034 }else if( strcmp(z,"-noheader")==0 ){ |
4829 data.showHeader = 0; | 6035 data.showHeader = 0; |
4830 }else if( strcmp(z,"-echo")==0 ){ | 6036 }else if( strcmp(z,"-echo")==0 ){ |
4831 data.echoOn = 1; | 6037 data.echoOn = 1; |
4832 }else if( strcmp(z,"-eqp")==0 ){ | 6038 }else if( strcmp(z,"-eqp")==0 ){ |
4833 data.autoEQP = 1; | 6039 data.autoEQP = 1; |
| 6040 }else if( strcmp(z,"-eqpfull")==0 ){ |
| 6041 data.autoEQP = 2; |
4834 }else if( strcmp(z,"-stats")==0 ){ | 6042 }else if( strcmp(z,"-stats")==0 ){ |
4835 data.statsOn = 1; | 6043 data.statsOn = 1; |
4836 }else if( strcmp(z,"-scanstats")==0 ){ | 6044 }else if( strcmp(z,"-scanstats")==0 ){ |
4837 data.scanstatsOn = 1; | 6045 data.scanstatsOn = 1; |
4838 }else if( strcmp(z,"-backslash")==0 ){ | 6046 }else if( strcmp(z,"-backslash")==0 ){ |
4839 /* Undocumented command-line option: -backslash | 6047 /* Undocumented command-line option: -backslash |
4840 ** Causes C-style backslash escapes to be evaluated in SQL statements | 6048 ** Causes C-style backslash escapes to be evaluated in SQL statements |
4841 ** prior to sending the SQL into SQLite. Useful for injecting | 6049 ** prior to sending the SQL into SQLite. Useful for injecting |
4842 ** crazy bytes in the middle of SQL statements for testing and debugging. | 6050 ** crazy bytes in the middle of SQL statements for testing and debugging. |
4843 */ | 6051 */ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4892 }else if( rc!=0 ){ | 6100 }else if( rc!=0 ){ |
4893 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z); | 6101 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z); |
4894 if( bail_on_error ) return rc; | 6102 if( bail_on_error ) return rc; |
4895 } | 6103 } |
4896 } | 6104 } |
4897 }else{ | 6105 }else{ |
4898 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); | 6106 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); |
4899 raw_printf(stderr,"Use -help for a list of options.\n"); | 6107 raw_printf(stderr,"Use -help for a list of options.\n"); |
4900 return 1; | 6108 return 1; |
4901 } | 6109 } |
| 6110 data.cMode = data.mode; |
4902 } | 6111 } |
4903 | 6112 |
4904 if( !readStdin ){ | 6113 if( !readStdin ){ |
4905 /* Run all arguments that do not begin with '-' as if they were separate | 6114 /* Run all arguments that do not begin with '-' as if they were separate |
4906 ** command-line inputs, except for the argToSkip argument which contains | 6115 ** command-line inputs, except for the argToSkip argument which contains |
4907 ** the database filename. | 6116 ** the database filename. |
4908 */ | 6117 */ |
4909 for(i=0; i<nCmd; i++){ | 6118 for(i=0; i<nCmd; i++){ |
4910 if( azCmd[i][0]=='.' ){ | 6119 if( azCmd[i][0]=='.' ){ |
4911 rc = do_meta_command(azCmd[i], &data); | 6120 rc = do_meta_command(azCmd[i], &data); |
(...skipping 22 matching lines...) Expand all Loading... |
4934 "SQLite version %s %.19s\n" /*extra-version-info*/ | 6143 "SQLite version %s %.19s\n" /*extra-version-info*/ |
4935 "Enter \".help\" for usage hints.\n", | 6144 "Enter \".help\" for usage hints.\n", |
4936 sqlite3_libversion(), sqlite3_sourceid() | 6145 sqlite3_libversion(), sqlite3_sourceid() |
4937 ); | 6146 ); |
4938 if( warnInmemoryDb ){ | 6147 if( warnInmemoryDb ){ |
4939 printf("Connected to a "); | 6148 printf("Connected to a "); |
4940 printBold("transient in-memory database"); | 6149 printBold("transient in-memory database"); |
4941 printf(".\nUse \".open FILENAME\" to reopen on a " | 6150 printf(".\nUse \".open FILENAME\" to reopen on a " |
4942 "persistent database.\n"); | 6151 "persistent database.\n"); |
4943 } | 6152 } |
4944 zHome = find_home_dir(); | 6153 zHome = find_home_dir(0); |
4945 if( zHome ){ | 6154 if( zHome ){ |
4946 nHistory = strlen30(zHome) + 20; | 6155 nHistory = strlen30(zHome) + 20; |
4947 if( (zHistory = malloc(nHistory))!=0 ){ | 6156 if( (zHistory = malloc(nHistory))!=0 ){ |
4948 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); | 6157 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); |
4949 } | 6158 } |
4950 } | 6159 } |
4951 if( zHistory ){ shell_read_history(zHistory); } | 6160 if( zHistory ){ shell_read_history(zHistory); } |
4952 rc = process_input(&data, 0); | 6161 rc = process_input(&data, 0); |
4953 if( zHistory ){ | 6162 if( zHistory ){ |
4954 shell_stifle_history(100); | 6163 shell_stifle_history(100); |
4955 shell_write_history(zHistory); | 6164 shell_write_history(zHistory); |
4956 free(zHistory); | 6165 free(zHistory); |
4957 } | 6166 } |
4958 }else{ | 6167 }else{ |
4959 rc = process_input(&data, stdin); | 6168 rc = process_input(&data, stdin); |
4960 } | 6169 } |
4961 } | 6170 } |
4962 set_table_name(&data, 0); | 6171 set_table_name(&data, 0); |
4963 if( data.db ){ | 6172 if( data.db ){ |
| 6173 session_close_all(&data); |
4964 sqlite3_close(data.db); | 6174 sqlite3_close(data.db); |
4965 } | 6175 } |
4966 sqlite3_free(data.zFreeOnClose); | 6176 sqlite3_free(data.zFreeOnClose); |
| 6177 find_home_dir(1); |
| 6178 #if !SQLITE_SHELL_IS_UTF8 |
| 6179 for(i=0; i<argc; i++) sqlite3_free(argv[i]); |
| 6180 sqlite3_free(argv); |
| 6181 #endif |
4967 return rc; | 6182 return rc; |
4968 } | 6183 } |
OLD | NEW |