Return to shell.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / elwix / files / sqlite / dist |
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.4 ! 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.4 ! 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.4 ! misho 65: #if HAVE_READLINE 1.2 misho 66: # include <readline/readline.h> 67: # include <readline/history.h> 68: #endif 1.4 ! 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.4 ! misho 100: 1.2 misho 101: #if defined(_WIN32) || defined(WIN32) 102: # include <io.h> 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 225: sqlite3_int64 iEnd = timeOfDay(); 1.2 misho 226: struct rusage sEnd; 227: getrusage(RUSAGE_SELF, &sEnd); 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 266: getProcessTimesAddr = ! 267: (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); 1.2 misho 268: if( NULL != getProcessTimesAddr ){ 269: return 1; 270: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 564: zResult = local_getline(zPrior, in); 1.2 misho 565: }else{ 1.4 ! 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); ! 575: #endif 1.2 misho 576: } 577: return zResult; 578: } 579: 1.4 ! 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.4 ! misho 606: ** State information about the database connection is contained in an ! 607: ** instance of the following structure. 1.2 misho 608: */ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 629: unsigned shellFlgs; /* Various flags */ 1.2 misho 630: char *zDestTable; /* Name of destination table when MODE_Insert */ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 684: "ascii", ! 685: "prettyprint", 1.2 misho 686: }; 687: 688: /* 1.4 ! misho 689: ** These are the column/row/line separators used by the various ! 690: ** import/export modes. 1.2 misho 691: */ 1.4 ! 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.4 ! misho 702: ** Number of elements in an array 1.2 misho 703: */ 1.4 ! 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.4 ! misho 710: ShellState *p = (ShellState*)pArg; 1.2 misho 711: if( p->pLog==0 ) return; 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 738: utf8_printf(out,"'%s'",z); 1.2 misho 739: }else{ 1.4 ! 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.4 ! misho 744: raw_printf(out,"''"); 1.2 misho 745: z++; 746: }else if( z[i]=='\'' ){ 1.4 ! misho 747: utf8_printf(out,"%.*s''",i,z); 1.2 misho 748: z += i+1; 749: }else{ 1.4 ! misho 750: utf8_printf(out,"%s",z); 1.2 misho 751: break; 752: } 753: } 1.4 ! misho 754: raw_printf(out,"'"); 1.2 misho 755: } 1.4 ! 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.4 ! 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.4 ! misho 796: if( z==0 ) z = ""; 1.2 misho 797: while( *z ){ 1.4 ! 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.4 ! misho 806: utf8_printf(out,"%.*s",i,z); 1.2 misho 807: } 808: if( z[i]=='<' ){ 1.4 ! misho 809: raw_printf(out,"<"); 1.2 misho 810: }else if( z[i]=='&' ){ 1.4 ! misho 811: raw_printf(out,"&"); 1.2 misho 812: }else if( z[i]=='>' ){ 1.4 ! misho 813: raw_printf(out,">"); 1.2 misho 814: }else if( z[i]=='\"' ){ 1.4 ! misho 815: raw_printf(out,"""); 1.2 misho 816: }else if( z[i]=='\'' ){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 857: utf8_printf(out,"%s",p->nullValue); 1.2 misho 858: }else{ 859: int i; 1.4 ! misho 860: int nSep = strlen30(p->colSeparator); 1.2 misho 861: for(i=0; z[i]; i++){ 1.4 ! 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.4 ! misho 877: utf8_printf(out, "%s", z); 1.2 misho 878: } 879: } 880: if( bSep ){ 1.4 ! 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.4 ! misho 891: seenInterrupt++; ! 892: if( seenInterrupt>2 ) exit(1); ! 893: if( globalDb ) sqlite3_interrupt(globalDb); 1.2 misho 894: } 895: #endif 896: 897: /* 1.4 ! 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.4 ! 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.4 ! misho 955: ShellState *p = (ShellState*)pArg; 1.2 misho 956: 1.4 ! 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.4 ! misho 965: if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); 1.2 misho 966: for(i=0; i<nArg; i++){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1004: if( showHdr ){ 1.3 misho 1005: if( w<0 ){ 1.4 ! misho 1006: utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], ! 1007: i==nArg-1 ? rowSep : " "); 1.3 misho 1008: }else{ 1.4 ! 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.4 ! 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.4 ! misho 1023: utf8_printf(p->out,"%-*.*s%s",w,w, ! 1024: "----------------------------------------------------------" 1.2 misho 1025: "----------------------------------------------------------", 1.4 ! 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.4 ! misho 1038: if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ 1.2 misho 1039: w = strlen30(azArg[i]); 1040: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1117: z[j] = 0; 1.2 misho 1118: } 1.4 ! 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.4 ! 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.4 ! misho 1133: if( z==0 ) z = p->nullValue; ! 1134: utf8_printf(p->out, "%s", z); 1.2 misho 1135: if( i<nArg-1 ){ 1.4 ! misho 1136: utf8_printf(p->out, "%s", p->colSeparator); 1.2 misho 1137: }else{ 1.4 ! 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.4 ! misho 1145: raw_printf(p->out,"<TR>"); 1.2 misho 1146: for(i=0; i<nArg; i++){ 1.4 ! misho 1147: raw_printf(p->out,"<TH>"); 1.2 misho 1148: output_html_string(p->out, azCol[i]); 1.4 ! misho 1149: raw_printf(p->out,"</TH>\n"); 1.2 misho 1150: } 1.4 ! misho 1151: raw_printf(p->out,"</TR>\n"); 1.2 misho 1152: } 1153: if( azArg==0 ) break; 1.4 ! misho 1154: raw_printf(p->out,"<TR>"); 1.2 misho 1155: for(i=0; i<nArg; i++){ 1.4 ! 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.4 ! 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.4 ! misho 1167: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator); 1.2 misho 1168: } 1.4 ! 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.4 ! 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.4 ! misho 1176: utf8_printf(p->out, "%s", p->rowSeparator); 1.2 misho 1177: break; 1178: } 1179: case MODE_Csv: { 1.4 ! 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.4 ! misho 1185: utf8_printf(p->out, "%s", p->rowSeparator); 1.2 misho 1186: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1212: utf8_printf(p->out,"%sNULL",zSep); 1.2 misho 1213: }else if( aiType && aiType[i]==SQLITE_TEXT ){ 1.4 ! misho 1214: if( zSep[0] ) utf8_printf(p->out,"%s",zSep); 1.2 misho 1215: output_quoted_string(p->out, azArg[i]); 1.4 ! 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.4 ! 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.4 ! misho 1225: utf8_printf(p->out,"%s%s",zSep, azArg[i]); 1.2 misho 1226: }else{ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1367: rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); 1.2 misho 1368: if( rc!=SQLITE_OK || !pSelect ){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1389: raw_printf(p->out, "\n;\n"); 1.3 misho 1390: }else{ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1467: 1.2 misho 1468: iHiwtr = iCur = -1; 1469: sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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; 1.4 ! misho 1543: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); ! 1544: raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", ! 1545: iCur); 1.2 misho 1546: iHiwtr = iCur = -1; 1547: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 1587: ** Display scan stats. 1.2 misho 1588: */ 1.4 ! misho 1589: static void display_scanstats( ! 1590: sqlite3 *db, /* Database to query */ ! 1591: ShellState *pArg /* Pointer to ShellState */ 1.2 misho 1592: ){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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; ! 1729: ! 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); 1.2 misho 1958: 1959: /* print usage stats if stats on */ 1960: if( pArg && pArg->statsOn ){ 1961: display_stats(db, pArg, 0); 1962: } 1963: 1.4 ! misho 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 1.2 misho 1970: ** copy of the error message. Otherwise, set zSql to point to the 1971: ** next statement to execute. */ 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.4 ! 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.4 ! misho 2011: 1.2 misho 2012: if( strcmp(zTable, "sqlite_sequence")==0 ){ 2013: zPrepStmt = "DELETE FROM sqlite_sequence;\n"; 1.4 ! 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.4 ! 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.4 ! misho 2028: utf8_printf(p->out, "%s\n", zIns); 1.2 misho 2029: sqlite3_free(zIns); 2030: return 0; 2031: }else{ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 2109: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); 1.2 misho 2110: if( zErr ){ 1.4 ! 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.4 ! 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.4 ! misho 2134: ".auth ON|OFF Show authorizer callbacks\n" 1.2 misho 2135: ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 2206: " Negative values right-justify\n" 1.2 misho 2207: ; 2208: 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 2377: ** \a -> alarm ! 2378: ** \b -> backspace 1.2 misho 2379: ** \t -> tab 2380: ** \n -> newline 1.4 ! misho 2381: ** \v -> vertical tab ! 2382: ** \f -> form feed 1.2 misho 2383: ** \r -> carriage return 1.4 ! misho 2384: ** \s -> space ! 2385: ** \" -> " ! 2386: ** \' -> ' ! 2387: ** \\ -> backslash 1.2 misho 2388: ** \NNN -> ascii character NNN in octal 2389: */ 2390: static void resolve_backslashes(char *z){ 2391: int i, j; 2392: char c; 1.4 ! misho 2393: while( *z && *z!='\\' ) z++; 1.2 misho 2394: for(i=j=0; (c = z[i])!=0; i++, j++){ 1.4 ! misho 2395: if( c=='\\' && z[i+1]!=0 ){ 1.2 misho 2396: c = z[++i]; 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 2431: if( j<i ) z[j] = 0; ! 2432: } ! 2433: ! 2434: /* ! 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; 1.2 misho 2489: } 2490: 2491: /* 1.4 ! misho 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.4 ! 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++){} 1.2 misho 2501: } 1.4 ! misho 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; ! 2508: } ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3165: if( zDb==0 ) zDb = "main"; 1.2 misho 3166: rc = sqlite3_open(zDestFile, &pDest); 3167: if( rc!=SQLITE_OK ){ 1.4 ! misho 3168: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); 1.2 misho 3169: sqlite3_close(pDest); 3170: return 1; 3171: } 1.4 ! misho 3172: open_db(p, 0); 1.2 misho 3173: pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); 3174: if( pBackup==0 ){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3240: open_db(p, 0); 1.2 misho 3241: memcpy(&data, p, sizeof(data)); 3242: data.showHeader = 1; 1.4 ! 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.4 ! misho 3250: utf8_printf(stderr,"Error: %s\n", zErrMsg); 1.2 misho 3251: sqlite3_free(zErrMsg); 3252: rc = 1; 3253: } 3254: }else 3255: 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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; ! 3360: } ! 3361: }else ! 3362: ! 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"); 1.2 misho 3415: } 3416: }else 3417: 1.4 ! 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; ! 3424: } 1.2 misho 3425: }else 3426: 3427: if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ 1.4 ! misho 3428: utf8_printf(p->out, "%s", zHelp); 1.2 misho 3429: }else 3430: 1.4 ! misho 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.4 ! 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.4 ! 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.4 ! misho 3467: raw_printf(stderr, "Error: non-null row separator required for import\n"); 1.2 misho 3468: return 1; 3469: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3556: zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); 1.2 misho 3557: if( zSql==0 ){ 1.4 ! misho 3558: raw_printf(stderr, "Error: out of memory\n"); ! 3559: xCloser(sCtx.in); 1.2 misho 3560: return 1; 3561: } 1.4 ! 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.4 ! misho 3570: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 3571: sqlite3_free(zSql); 1.2 misho 3572: if( rc ){ 1.4 ! misho 3573: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1.2 misho 3574: if (pStmt) sqlite3_finalize(pStmt); 1.4 ! misho 3575: xCloser(sCtx.in); 1.2 misho 3576: return 1; 3577: } 1.4 ! 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++; } ! 3602: } ! 3603: } ! 3604: if( sCtx.cTerm==sCtx.cColSep ){ ! 3605: do{ ! 3606: xRead(&sCtx); 1.2 misho 3607: i++; 1.4 ! misho 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)); 1.2 misho 3619: } 3620: } 1.4 ! misho 3621: }while( sCtx.cTerm!=EOF ); ! 3622: ! 3623: xCloser(sCtx.in); ! 3624: sqlite3_free(sCtx.z); 1.2 misho 3625: sqlite3_finalize(pStmt); 1.4 ! misho 3626: if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); 1.2 misho 3627: }else 3628: 1.4 ! 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.4 ! misho 3633: open_db(p, 0); 1.2 misho 3634: memcpy(&data, p, sizeof(data)); 3635: data.showHeader = 0; 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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; 1.4 ! misho 3685: }else{ ! 3686: iotrace = fopen(azArg[1], "w"); ! 3687: if( iotrace==0 ){ ! 3688: utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); ! 3689: sqlite3IoTrace = 0; ! 3690: rc = 1; ! 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]); 1.2 misho 3744: rc = 1; 1.4 ! misho 3745: goto meta_command_exit; ! 3746: } ! 3747: if( nArg==3 ){ ! 3748: sqlite3_limit(p->db, aLimit[iLimit].limitCode, ! 3749: (int)integerValue(azArg[2])); 1.2 misho 3750: } 1.4 ! misho 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.4 ! misho 3757: if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ 1.2 misho 3758: const char *zFile, *zProc; 3759: char *zErrMsg = 0; 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3794: }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ 1.2 misho 3795: p->mode = MODE_Column; 1.4 ! misho 3796: }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ 1.2 misho 3797: p->mode = MODE_List; 1.4 ! misho 3798: }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ 1.2 misho 3799: p->mode = MODE_Html; 1.4 ! misho 3800: }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ 1.2 misho 3801: p->mode = MODE_Tcl; 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3822: p->cMode = p->mode; 1.2 misho 3823: }else 3824: 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3872: p->outCount = 0; 1.2 misho 3873: } 1.4 ! 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.4 ! 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.4 ! misho 3887: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); 1.3 misho 3888: } 1.4 ! misho 3889: #endif 1.2 misho 3890: }else{ 1.4 ! misho 3891: p->out = output_file_open(zFile); 1.2 misho 3892: if( p->out==0 ){ 1.4 ! 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.4 ! 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.4 ! misho 3907: if( i>1 ) raw_printf(p->out, " "); ! 3908: utf8_printf(p->out, "%s", azArg[i]); 1.3 misho 3909: } 1.4 ! misho 3910: raw_printf(p->out, "\n"); 1.3 misho 3911: }else 3912: 1.4 ! 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.4 ! misho 3922: if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ 1.2 misho 3923: rc = 2; 3924: }else 3925: 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 3953: }else if( nArg==3 ){ 1.2 misho 3954: zSrcFile = azArg[2]; 3955: zDb = azArg[1]; 1.4 ! 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.4 ! misho 3963: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); 1.2 misho 3964: sqlite3_close(pSrc); 3965: return 1; 3966: } 1.4 ! misho 3967: open_db(p, 0); 1.2 misho 3968: pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); 3969: if( pBackup==0 ){ 1.4 ! 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.4 ! misho 3985: raw_printf(stderr, "Error: source database is busy\n"); 1.2 misho 3986: rc = 1; 3987: }else{ 1.4 ! 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.4 ! 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.4 ! misho 4010: open_db(p, 0); 1.2 misho 4011: memcpy(&data, p, sizeof(data)); 4012: data.showHeader = 0; 1.4 ! 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.4 ! misho 4059: "ORDER BY rowid", 1.2 misho 4060: callback, &data, &zErrMsg); 4061: zShellStatic = 0; 4062: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4378: raw_printf(p->out, "%d ", p->colWidth[i]); 1.2 misho 4379: } 1.4 ! misho 4380: raw_printf(p->out, "\n"); 1.2 misho 4381: }else 4382: 1.4 ! 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.4 ! 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.4 ! misho 4400: open_db(p, 0); 1.3 misho 4401: rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4452: int n2 = nAlloc*2 + 10; ! 4453: azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); 1.3 misho 4454: if( azNew==0 ){ 1.4 ! misho 4455: rc = shellNomemError(); 1.3 misho 4456: break; 4457: } 1.4 ! misho 4458: nAlloc = n2; 1.3 misho 4459: azResult = azNew; 4460: } 4461: azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); 1.4 ! misho 4462: if( 0==azResult[nRow] ){ ! 4463: rc = shellNomemError(); ! 4464: break; ! 4465: } ! 4466: nRow++; 1.2 misho 4467: } 1.4 ! 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.4 ! misho 4487: utf8_printf(p->out, "%s%-*s", zSp, maxlen, ! 4488: azResult[j] ? azResult[j]:""); 1.2 misho 4489: } 1.4 ! misho 4490: raw_printf(p->out, "\n"); 1.2 misho 4491: } 4492: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4533: utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]); 1.2 misho 4534: testctrl = -1; 4535: break; 4536: } 4537: } 4538: } 1.4 ! misho 4539: if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); 1.2 misho 4540: if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){ 1.4 ! 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.4 ! misho 4547: case SQLITE_TESTCTRL_RESERVE: 1.2 misho 4548: if( nArg==3 ){ 1.4 ! 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.4 ! 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.4 ! misho 4559: case SQLITE_TESTCTRL_PRNG_SAVE: ! 4560: case SQLITE_TESTCTRL_PRNG_RESTORE: 1.2 misho 4561: case SQLITE_TESTCTRL_PRNG_RESET: 1.4 ! misho 4562: case SQLITE_TESTCTRL_BYTEORDER: 1.2 misho 4563: if( nArg==2 ){ 1.4 ! misho 4564: rc2 = sqlite3_test_control(testctrl); ! 4565: raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); 1.2 misho 4566: } else { 1.4 ! 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.4 ! misho 4573: case SQLITE_TESTCTRL_PENDING_BYTE: 1.2 misho 4574: if( nArg==3 ){ 1.4 ! 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.4 ! 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.4 ! misho 4583: 1.2 misho 4584: /* sqlite3_test_control(int, int) */ 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4600: case SQLITE_TESTCTRL_ISKEYWORD: 1.2 misho 4601: if( nArg==3 ){ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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); ! 4641: }else ! 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: } 1.2 misho 4654: }else 1.4 ! misho 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.4 ! misho 4667: sqlite3_trace_v2(p->db, 0, 0, 0); 1.3 misho 4668: }else{ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4790: sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; 1.3 misho 4791: }else 4792: #endif 4793: 1.4 ! 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.4 ! misho 4798: p->colWidth[j-1] = (int)integerValue(azArg[j]); 1.2 misho 4799: } 4800: }else 4801: 4802: { 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 4930: if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ 1.2 misho 4931: memcpy(zLine,";",2); 4932: } 1.4 ! 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.4 ! misho 4943: if( nSql==0 ){ 1.2 misho 4944: int i; 4945: for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} 1.4 ! 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.4 ! misho 4952: memcpy(zSql+nSql, zLine, nLine+1); ! 4953: nSql += nLine; 1.2 misho 4954: } 1.4 ! misho 4955: if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) 1.2 misho 4956: && sqlite3_complete(zSql) ){ 4957: p->cnt = 0; 1.4 ! 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.4 ! 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.4 ! misho 4972: utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); 1.2 misho 4973: sqlite3_free(zErrMsg); 4974: zErrMsg = 0; 4975: }else{ 1.4 ! misho 4976: utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); 1.2 misho 4977: } 4978: errCnt++; 1.4 ! 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.4 ! 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.4 ! misho 4993: if( nSql ){ 1.2 misho 4994: if( !_all_whitespace(zSql) ){ 1.4 ! misho 4995: utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql); ! 4996: errCnt++; 1.2 misho 4997: } 4998: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5097: utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); 1.2 misho 5098: } 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5149: utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); 1.2 misho 5150: }else{ 1.4 ! 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.4 ! misho 5159: static void main_init(ShellState *data) { 1.2 misho 5160: memset(data, 0, sizeof(*data)); 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5222: ShellState data; 1.2 misho 5223: const char *zInitFile = 0; 5224: int i; 5225: int rc = 0; 1.4 ! 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.4 ! misho 5236: #if USE_SYSTEM_SQLITE+0!=1 1.2 misho 5237: if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ 1.4 ! 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.4 ! misho 5242: #endif ! 5243: main_init(&data); ! 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] ); 1.2 misho 5260: Argv0 = argv[0]; 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5329: #else ! 5330: (void)cmdline_option_value(argc, argv, ++i); 1.2 misho 5331: #endif 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5391: warnInmemoryDb = argc==1; 1.2 misho 5392: #else 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5512: if( rc && bail_on_error ) return rc==2 ? 0 : rc; 1.3 misho 5513: }else{ 1.4 ! 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.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5529: data.cMode = data.mode; 1.2 misho 5530: } 5531: 1.4 ! 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.4 ! 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.4 ! 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.4 ! misho 5563: "Enter \".help\" for usage hints.\n", 1.2 misho 5564: sqlite3_libversion(), sqlite3_sourceid() 5565: ); 1.4 ! 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.4 ! misho 5579: if( zHistory ){ shell_read_history(zHistory); } 1.2 misho 5580: rc = process_input(&data, 0); 5581: if( zHistory ){ 1.4 ! 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.4 ! misho 5592: session_close_all(&data); 1.2 misho 5593: sqlite3_close(data.db); 5594: } 1.4 ! 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: }