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