Return to shell.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / elwix / files / sqlite / dist |
1.5 ! misho 1: /* DO NOT EDIT! ! 2: ** This file is automatically generated by the script in the canonical ! 3: ** SQLite source tree at tool/mkshellc.tcl. That script combines source ! 4: ** code from various constituent source files of SQLite into this single ! 5: ** "shell.c" file used to implement the SQLite command-line shell. ! 6: ** ! 7: ** Most of the code found below comes from the "src/shell.c.in" file in ! 8: ** the canonical SQLite source tree. That main file contains "INCLUDE" ! 9: ** lines that specify other files in the canonical source tree that are ! 10: ** inserted to getnerate this complete program source file. ! 11: ** ! 12: ** The code from multiple files is combined into this single "shell.c" ! 13: ** source file to help make the command-line program easier to compile. ! 14: ** ! 15: ** To modify this program, get a copy of the canonical SQLite source tree, ! 16: ** edit the src/shell.c.in" and/or some of the other files that are included ! 17: ** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script. ! 18: */ 1.2 misho 19: /* 20: ** 2001 September 15 21: ** 22: ** The author disclaims copyright to this source code. In place of 23: ** a legal notice, here is a blessing: 24: ** 25: ** May you do good and not evil. 26: ** May you find forgiveness for yourself and forgive others. 27: ** May you share freely, never taking more than you give. 28: ** 29: ************************************************************************* 30: ** This file contains code to implement the "sqlite" command line 31: ** utility for accessing SQLite databases. 32: */ 33: #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) 34: /* This needs to come before any includes for MSVC compiler */ 35: #define _CRT_SECURE_NO_WARNINGS 36: #endif 37: 38: /* 1.5 ! misho 39: ** Determine if we are dealing with WinRT, which provides only a subset of ! 40: ** the full Win32 API. 1.4 misho 41: */ 1.5 ! misho 42: #if !defined(SQLITE_OS_WINRT) ! 43: # define SQLITE_OS_WINRT 0 1.4 misho 44: #endif 45: 46: /* 1.5 ! misho 47: ** Warning pragmas copied from msvc.h in the core. ! 48: */ ! 49: #if defined(_MSC_VER) ! 50: #pragma warning(disable : 4054) ! 51: #pragma warning(disable : 4055) ! 52: #pragma warning(disable : 4100) ! 53: #pragma warning(disable : 4127) ! 54: #pragma warning(disable : 4130) ! 55: #pragma warning(disable : 4152) ! 56: #pragma warning(disable : 4189) ! 57: #pragma warning(disable : 4206) ! 58: #pragma warning(disable : 4210) ! 59: #pragma warning(disable : 4232) ! 60: #pragma warning(disable : 4244) ! 61: #pragma warning(disable : 4305) ! 62: #pragma warning(disable : 4306) ! 63: #pragma warning(disable : 4702) ! 64: #pragma warning(disable : 4706) ! 65: #endif /* defined(_MSC_VER) */ ! 66: ! 67: /* 1.4 misho 68: ** No support for loadable extensions in VxWorks. 69: */ 70: #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION 71: # define SQLITE_OMIT_LOAD_EXTENSION 1 72: #endif 73: 74: /* 1.2 misho 75: ** Enable large-file support for fopen() and friends on unix. 76: */ 77: #ifndef SQLITE_DISABLE_LFS 78: # define _LARGE_FILE 1 79: # ifndef _FILE_OFFSET_BITS 80: # define _FILE_OFFSET_BITS 64 81: # endif 82: # define _LARGEFILE_SOURCE 1 83: #endif 84: 85: #include <stdlib.h> 86: #include <string.h> 87: #include <stdio.h> 88: #include <assert.h> 89: #include "sqlite3.h" 1.5 ! misho 90: typedef sqlite3_int64 i64; ! 91: typedef sqlite3_uint64 u64; ! 92: typedef unsigned char u8; 1.4 misho 93: #if SQLITE_USER_AUTHENTICATION 94: # include "sqlite3userauth.h" 95: #endif 1.2 misho 96: #include <ctype.h> 97: #include <stdarg.h> 98: 1.3 misho 99: #if !defined(_WIN32) && !defined(WIN32) 1.2 misho 100: # include <signal.h> 101: # if !defined(__RTP__) && !defined(_WRS_KERNEL) 102: # include <pwd.h> 103: # endif 1.5 ! misho 104: #endif ! 105: #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) 1.2 misho 106: # include <unistd.h> 1.5 ! misho 107: # include <dirent.h> ! 108: # define GETPID getpid ! 109: # if defined(__MINGW32__) ! 110: # define DIRENT dirent ! 111: # ifndef S_ISLNK ! 112: # define S_ISLNK(mode) (0) ! 113: # endif ! 114: # endif ! 115: #else ! 116: # define GETPID (int)GetCurrentProcessId 1.2 misho 117: #endif 1.5 ! misho 118: #include <sys/types.h> ! 119: #include <sys/stat.h> 1.2 misho 120: 1.4 misho 121: #if HAVE_READLINE 1.2 misho 122: # include <readline/readline.h> 123: # include <readline/history.h> 124: #endif 1.4 misho 125: 126: #if HAVE_EDITLINE 127: # include <editline/readline.h> 128: #endif 129: 130: #if HAVE_EDITLINE || HAVE_READLINE 131: 132: # define shell_add_history(X) add_history(X) 133: # define shell_read_history(X) read_history(X) 134: # define shell_write_history(X) write_history(X) 135: # define shell_stifle_history(X) stifle_history(X) 136: # define shell_readline(X) readline(X) 137: 138: #elif HAVE_LINENOISE 139: 140: # include "linenoise.h" 141: # define shell_add_history(X) linenoiseHistoryAdd(X) 142: # define shell_read_history(X) linenoiseHistoryLoad(X) 143: # define shell_write_history(X) linenoiseHistorySave(X) 144: # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) 145: # define shell_readline(X) linenoise(X) 146: 147: #else 148: 149: # define shell_read_history(X) 150: # define shell_write_history(X) 151: # define shell_stifle_history(X) 152: 153: # define SHELL_USE_LOCAL_GETLINE 1 1.2 misho 154: #endif 155: 1.4 misho 156: 1.2 misho 157: #if defined(_WIN32) || defined(WIN32) 1.5 ! misho 158: # if SQLITE_OS_WINRT ! 159: # define SQLITE_OMIT_POPEN 1 ! 160: # else ! 161: # include <io.h> ! 162: # include <fcntl.h> ! 163: # define isatty(h) _isatty(h) ! 164: # ifndef access ! 165: # define access(f,m) _access((f),(m)) ! 166: # endif ! 167: # ifndef unlink ! 168: # define unlink _unlink ! 169: # endif ! 170: # ifndef strdup ! 171: # define strdup _strdup ! 172: # endif ! 173: # undef popen ! 174: # define popen _popen ! 175: # undef pclose ! 176: # define pclose _pclose 1.4 misho 177: # endif 1.2 misho 178: #else 1.4 misho 179: /* Make sure isatty() has a prototype. */ 180: extern int isatty(int); 181: 182: # if !defined(__RTP__) && !defined(_WRS_KERNEL) 183: /* popen and pclose are not C89 functions and so are 184: ** sometimes omitted from the <stdio.h> header */ 185: extern FILE *popen(const char*,const char*); 186: extern int pclose(FILE*); 187: # else 188: # define SQLITE_OMIT_POPEN 1 189: # endif 1.2 misho 190: #endif 191: 192: #if defined(_WIN32_WCE) 193: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() 194: * thus we always assume that we have a console. That can be 195: * overridden with the -batch command line option. 196: */ 197: #define isatty(x) 1 198: #endif 199: 200: /* ctype macros that work with signed characters */ 201: #define IsSpace(X) isspace((unsigned char)X) 202: #define IsDigit(X) isdigit((unsigned char)X) 203: #define ToLower(X) (char)tolower((unsigned char)X) 204: 1.4 misho 205: #if defined(_WIN32) || defined(WIN32) 1.5 ! misho 206: #if SQLITE_OS_WINRT ! 207: #include <intrin.h> ! 208: #endif 1.4 misho 209: #include <windows.h> 210: 211: /* string conversion routines only needed on Win32 */ 212: extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); 213: extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int); 214: extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int); 1.5 ! misho 215: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); 1.4 misho 216: #endif 217: 218: /* On Windows, we normally run with output mode of TEXT so that \n characters 219: ** are automatically translated into \r\n. However, this behavior needs 220: ** to be disabled in some cases (ex: when generating CSV output and when 221: ** rendering quoted strings that contain \n characters). The following 222: ** routines take care of that. 223: */ 1.5 ! misho 224: #if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT 1.4 misho 225: static void setBinaryMode(FILE *file, int isOutput){ 226: if( isOutput ) fflush(file); 227: _setmode(_fileno(file), _O_BINARY); 228: } 229: static void setTextMode(FILE *file, int isOutput){ 230: if( isOutput ) fflush(file); 231: _setmode(_fileno(file), _O_TEXT); 232: } 233: #else 234: # define setBinaryMode(X,Y) 235: # define setTextMode(X,Y) 236: #endif 237: 238: 239: /* True if the timer is enabled */ 240: static int enableTimer = 0; 241: 242: /* Return the current wall-clock time */ 243: static sqlite3_int64 timeOfDay(void){ 244: static sqlite3_vfs *clockVfs = 0; 245: sqlite3_int64 t; 246: if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); 247: if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ 248: clockVfs->xCurrentTimeInt64(clockVfs, &t); 249: }else{ 250: double r; 251: clockVfs->xCurrentTime(clockVfs, &r); 252: t = (sqlite3_int64)(r*86400000.0); 253: } 254: return t; 255: } 256: 257: #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) 1.2 misho 258: #include <sys/time.h> 259: #include <sys/resource.h> 260: 1.4 misho 261: /* VxWorks does not support getrusage() as far as we can determine */ 262: #if defined(_WRS_KERNEL) || defined(__RTP__) 263: struct rusage { 264: struct timeval ru_utime; /* user CPU time used */ 265: struct timeval ru_stime; /* system CPU time used */ 266: }; 267: #define getrusage(A,B) memset(B,0,sizeof(*B)) 268: #endif 269: 1.2 misho 270: /* Saved resource information for the beginning of an operation */ 1.4 misho 271: static struct rusage sBegin; /* CPU time at start */ 272: static sqlite3_int64 iBegin; /* Wall-clock time at start */ 1.2 misho 273: 274: /* 275: ** Begin timing an operation 276: */ 277: static void beginTimer(void){ 278: if( enableTimer ){ 279: getrusage(RUSAGE_SELF, &sBegin); 1.4 misho 280: iBegin = timeOfDay(); 1.2 misho 281: } 282: } 283: 284: /* Return the difference of two time_structs in seconds */ 285: static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ 1.4 misho 286: return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + 1.2 misho 287: (double)(pEnd->tv_sec - pStart->tv_sec); 288: } 289: 290: /* 291: ** Print the timing results. 292: */ 293: static void endTimer(void){ 294: if( enableTimer ){ 1.4 misho 295: sqlite3_int64 iEnd = timeOfDay(); 1.2 misho 296: struct rusage sEnd; 297: getrusage(RUSAGE_SELF, &sEnd); 1.4 misho 298: printf("Run Time: real %.3f user %f sys %f\n", 299: (iEnd - iBegin)*0.001, 1.2 misho 300: timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), 301: timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); 302: } 303: } 304: 305: #define BEGIN_TIMER beginTimer() 306: #define END_TIMER endTimer() 307: #define HAS_TIMER 1 308: 309: #elif (defined(_WIN32) || defined(WIN32)) 310: 311: /* Saved resource information for the beginning of an operation */ 312: static HANDLE hProcess; 313: static FILETIME ftKernelBegin; 314: static FILETIME ftUserBegin; 1.4 misho 315: static sqlite3_int64 ftWallBegin; 316: typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, 317: LPFILETIME, LPFILETIME); 1.2 misho 318: static GETPROCTIMES getProcessTimesAddr = NULL; 319: 320: /* 321: ** Check to see if we have timer support. Return 1 if necessary 322: ** support found (or found previously). 323: */ 324: static int hasTimer(void){ 325: if( getProcessTimesAddr ){ 326: return 1; 327: } else { 1.5 ! misho 328: #if !SQLITE_OS_WINRT 1.4 misho 329: /* GetProcessTimes() isn't supported in WIN95 and some other Windows 330: ** versions. See if the version we are running on has it, and if it 331: ** does, save off a pointer to it and the current process handle. 1.2 misho 332: */ 333: hProcess = GetCurrentProcess(); 334: if( hProcess ){ 335: HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); 336: if( NULL != hinstLib ){ 1.4 misho 337: getProcessTimesAddr = 338: (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); 1.2 misho 339: if( NULL != getProcessTimesAddr ){ 340: return 1; 341: } 1.4 misho 342: FreeLibrary(hinstLib); 1.2 misho 343: } 344: } 1.5 ! misho 345: #endif 1.2 misho 346: } 347: return 0; 348: } 349: 350: /* 351: ** Begin timing an operation 352: */ 353: static void beginTimer(void){ 354: if( enableTimer && getProcessTimesAddr ){ 355: FILETIME ftCreation, ftExit; 1.4 misho 356: getProcessTimesAddr(hProcess,&ftCreation,&ftExit, 357: &ftKernelBegin,&ftUserBegin); 358: ftWallBegin = timeOfDay(); 1.2 misho 359: } 360: } 361: 362: /* Return the difference of two FILETIME structs in seconds */ 363: static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ 364: sqlite_int64 i64Start = *((sqlite_int64 *) pStart); 365: sqlite_int64 i64End = *((sqlite_int64 *) pEnd); 366: return (double) ((i64End - i64Start) / 10000000.0); 367: } 368: 369: /* 370: ** Print the timing results. 371: */ 372: static void endTimer(void){ 373: if( enableTimer && getProcessTimesAddr){ 374: FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; 1.4 misho 375: sqlite3_int64 ftWallEnd = timeOfDay(); 376: getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); 377: printf("Run Time: real %.3f user %f sys %f\n", 378: (ftWallEnd - ftWallBegin)*0.001, 1.2 misho 379: timeDiff(&ftUserBegin, &ftUserEnd), 380: timeDiff(&ftKernelBegin, &ftKernelEnd)); 381: } 382: } 383: 384: #define BEGIN_TIMER beginTimer() 385: #define END_TIMER endTimer() 386: #define HAS_TIMER hasTimer() 387: 388: #else 1.4 misho 389: #define BEGIN_TIMER 1.2 misho 390: #define END_TIMER 391: #define HAS_TIMER 0 392: #endif 393: 394: /* 395: ** Used to prevent warnings about unused parameters 396: */ 397: #define UNUSED_PARAMETER(x) (void)(x) 398: 399: /* 1.5 ! misho 400: ** Number of elements in an array ! 401: */ ! 402: #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) ! 403: ! 404: /* 1.2 misho 405: ** If the following flag is set, then command execution stops 406: ** at an error if we are not interactive. 407: */ 408: static int bail_on_error = 0; 409: 410: /* 411: ** Threat stdin as an interactive input if the following variable 412: ** is true. Otherwise, assume stdin is connected to a file or pipe. 413: */ 414: static int stdin_is_interactive = 1; 415: 416: /* 1.4 misho 417: ** On Windows systems we have to know if standard output is a console 418: ** in order to translate UTF-8 into MBCS. The following variable is 419: ** true if translation is required. 420: */ 421: static int stdout_is_console = 1; 422: 423: /* 1.2 misho 424: ** The following is the open SQLite database. We make a pointer 425: ** to this database a static variable so that it can be accessed 426: ** by the SIGINT handler to interrupt database processing. 427: */ 1.4 misho 428: static sqlite3 *globalDb = 0; 1.2 misho 429: 430: /* 431: ** True if an interrupt (Control-C) has been received. 432: */ 433: static volatile int seenInterrupt = 0; 434: 1.5 ! misho 435: #ifdef SQLITE_DEBUG ! 436: /* ! 437: ** Out-of-memory simulator variables ! 438: */ ! 439: static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */ ! 440: static unsigned int oomRepeat = 0; /* Number of OOMs in a row */ ! 441: static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */ ! 442: #endif /* SQLITE_DEBUG */ ! 443: 1.2 misho 444: /* 445: ** This is the name of our program. It is set in main(), used 446: ** in a number of other places, mostly for error messages. 447: */ 448: static char *Argv0; 449: 450: /* 451: ** Prompt strings. Initialized in main. Settable with 452: ** .prompt main continue 453: */ 454: static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ 455: static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ 456: 457: /* 1.4 misho 458: ** Render output like fprintf(). Except, if the output is going to the 459: ** console and if this is running on a Windows machine, translate the 460: ** output from UTF-8 into MBCS. 461: */ 462: #if defined(_WIN32) || defined(WIN32) 463: void utf8_printf(FILE *out, const char *zFormat, ...){ 464: va_list ap; 465: va_start(ap, zFormat); 466: if( stdout_is_console && (out==stdout || out==stderr) ){ 467: char *z1 = sqlite3_vmprintf(zFormat, ap); 468: char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); 469: sqlite3_free(z1); 470: fputs(z2, out); 471: sqlite3_free(z2); 472: }else{ 473: vfprintf(out, zFormat, ap); 474: } 475: va_end(ap); 476: } 477: #elif !defined(utf8_printf) 478: # define utf8_printf fprintf 479: #endif 480: 481: /* 482: ** Render output like fprintf(). This should not be used on anything that 483: ** includes string formatting (e.g. "%s"). 484: */ 485: #if !defined(raw_printf) 486: # define raw_printf fprintf 487: #endif 488: 1.5 ! misho 489: /* Indicate out-of-memory and exit. */ ! 490: static void shell_out_of_memory(void){ ! 491: raw_printf(stderr,"Error: out of memory\n"); ! 492: exit(1); ! 493: } ! 494: ! 495: #ifdef SQLITE_DEBUG ! 496: /* This routine is called when a simulated OOM occurs. It is broken ! 497: ** out as a separate routine to make it easy to set a breakpoint on ! 498: ** the OOM ! 499: */ ! 500: void shellOomFault(void){ ! 501: if( oomRepeat>0 ){ ! 502: oomRepeat--; ! 503: }else{ ! 504: oomCounter--; ! 505: } ! 506: } ! 507: #endif /* SQLITE_DEBUG */ ! 508: ! 509: #ifdef SQLITE_DEBUG ! 510: /* This routine is a replacement malloc() that is used to simulate ! 511: ** Out-Of-Memory (OOM) errors for testing purposes. ! 512: */ ! 513: static void *oomMalloc(int nByte){ ! 514: if( oomCounter ){ ! 515: if( oomCounter==1 ){ ! 516: shellOomFault(); ! 517: return 0; ! 518: }else{ ! 519: oomCounter--; ! 520: } ! 521: } ! 522: return defaultMalloc(nByte); ! 523: } ! 524: #endif /* SQLITE_DEBUG */ ! 525: ! 526: #ifdef SQLITE_DEBUG ! 527: /* Register the OOM simulator. This must occur before any memory ! 528: ** allocations */ ! 529: static void registerOomSimulator(void){ ! 530: sqlite3_mem_methods mem; ! 531: sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem); ! 532: defaultMalloc = mem.xMalloc; ! 533: mem.xMalloc = oomMalloc; ! 534: sqlite3_config(SQLITE_CONFIG_MALLOC, &mem); ! 535: } ! 536: #endif ! 537: 1.4 misho 538: /* 1.2 misho 539: ** Write I/O traces to the following stream. 540: */ 541: #ifdef SQLITE_ENABLE_IOTRACE 542: static FILE *iotrace = 0; 543: #endif 544: 545: /* 546: ** This routine works like printf in that its first argument is a 547: ** format string and subsequent arguments are values to be substituted 548: ** in place of % fields. The result of formatting this string 549: ** is written to iotrace. 550: */ 551: #ifdef SQLITE_ENABLE_IOTRACE 1.4 misho 552: static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ 1.2 misho 553: va_list ap; 554: char *z; 555: if( iotrace==0 ) return; 556: va_start(ap, zFormat); 557: z = sqlite3_vmprintf(zFormat, ap); 558: va_end(ap); 1.4 misho 559: utf8_printf(iotrace, "%s", z); 1.2 misho 560: sqlite3_free(z); 561: } 562: #endif 563: 1.5 ! misho 564: /* ! 565: ** Output string zUtf to stream pOut as w characters. If w is negative, ! 566: ** then right-justify the text. W is the width in UTF-8 characters, not ! 567: ** in bytes. This is different from the %*.*s specification in printf ! 568: ** since with %*.*s the width is measured in bytes, not characters. ! 569: */ ! 570: static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ ! 571: int i; ! 572: int n; ! 573: int aw = w<0 ? -w : w; ! 574: char zBuf[1000]; ! 575: if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3; ! 576: for(i=n=0; zUtf[i]; i++){ ! 577: if( (zUtf[i]&0xc0)!=0x80 ){ ! 578: n++; ! 579: if( n==aw ){ ! 580: do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); ! 581: break; ! 582: } ! 583: } ! 584: } ! 585: if( n>=aw ){ ! 586: utf8_printf(pOut, "%.*s", i, zUtf); ! 587: }else if( w<0 ){ ! 588: utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); ! 589: }else{ ! 590: utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); ! 591: } ! 592: } ! 593: 1.2 misho 594: 595: /* 596: ** Determines if a string is a number of not. 597: */ 598: static int isNumber(const char *z, int *realnum){ 599: if( *z=='-' || *z=='+' ) z++; 600: if( !IsDigit(*z) ){ 601: return 0; 602: } 603: z++; 604: if( realnum ) *realnum = 0; 605: while( IsDigit(*z) ){ z++; } 606: if( *z=='.' ){ 607: z++; 608: if( !IsDigit(*z) ) return 0; 609: while( IsDigit(*z) ){ z++; } 610: if( realnum ) *realnum = 1; 611: } 612: if( *z=='e' || *z=='E' ){ 613: z++; 614: if( *z=='+' || *z=='-' ) z++; 615: if( !IsDigit(*z) ) return 0; 616: while( IsDigit(*z) ){ z++; } 617: if( realnum ) *realnum = 1; 618: } 619: return *z==0; 620: } 621: 622: /* 1.4 misho 623: ** Compute a string length that is limited to what can be stored in 624: ** lower 30 bits of a 32-bit signed integer. 625: */ 626: static int strlen30(const char *z){ 627: const char *z2 = z; 628: while( *z2 ){ z2++; } 629: return 0x3fffffff & (int)(z2 - z); 630: } 631: 632: /* 1.5 ! misho 633: ** Return the length of a string in characters. Multibyte UTF8 characters ! 634: ** count as a single character. ! 635: */ ! 636: static int strlenChar(const char *z){ ! 637: int n = 0; ! 638: while( *z ){ ! 639: if( (0xc0&*(z++))!=0x80 ) n++; ! 640: } ! 641: return n; ! 642: } ! 643: ! 644: /* ! 645: ** Return true if zFile does not exist or if it is not an ordinary file. ! 646: */ ! 647: #ifdef _WIN32 ! 648: # define notNormalFile(X) 0 ! 649: #else ! 650: static int notNormalFile(const char *zFile){ ! 651: struct stat x; ! 652: int rc; ! 653: memset(&x, 0, sizeof(x)); ! 654: rc = stat(zFile, &x); ! 655: return rc || !S_ISREG(x.st_mode); ! 656: } ! 657: #endif ! 658: ! 659: /* 1.2 misho 660: ** This routine reads a line of text from FILE in, stores 661: ** the text in memory obtained from malloc() and returns a pointer 662: ** to the text. NULL is returned at end of file, or if malloc() 663: ** fails. 664: ** 1.4 misho 665: ** If zLine is not NULL then it is a malloced buffer returned from 666: ** a previous call to this routine that may be reused. 1.2 misho 667: */ 1.4 misho 668: static char *local_getline(char *zLine, FILE *in){ 669: int nLine = zLine==0 ? 0 : 100; 670: int n = 0; 1.2 misho 671: 672: while( 1 ){ 673: if( n+100>nLine ){ 674: nLine = nLine*2 + 100; 675: zLine = realloc(zLine, nLine); 1.5 ! misho 676: if( zLine==0 ) shell_out_of_memory(); 1.2 misho 677: } 678: if( fgets(&zLine[n], nLine - n, in)==0 ){ 679: if( n==0 ){ 680: free(zLine); 681: return 0; 682: } 683: zLine[n] = 0; 684: break; 685: } 1.4 misho 686: while( zLine[n] ) n++; 687: if( n>0 && zLine[n-1]=='\n' ){ 1.2 misho 688: n--; 689: if( n>0 && zLine[n-1]=='\r' ) n--; 690: zLine[n] = 0; 691: break; 692: } 693: } 1.4 misho 694: #if defined(_WIN32) || defined(WIN32) 695: /* For interactive input on Windows systems, translate the 696: ** multi-byte characterset characters into UTF-8. */ 697: if( stdin_is_interactive && in==stdin ){ 698: char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); 699: if( zTrans ){ 700: int nTrans = strlen30(zTrans)+1; 701: if( nTrans>nLine ){ 702: zLine = realloc(zLine, nTrans); 1.5 ! misho 703: if( zLine==0 ) shell_out_of_memory(); 1.4 misho 704: } 705: memcpy(zLine, zTrans, nTrans); 706: sqlite3_free(zTrans); 707: } 708: } 709: #endif /* defined(_WIN32) || defined(WIN32) */ 1.2 misho 710: return zLine; 711: } 712: 713: /* 714: ** Retrieve a single line of input text. 715: ** 1.4 misho 716: ** If in==0 then read from standard input and prompt before each line. 717: ** If isContinuation is true, then a continuation prompt is appropriate. 718: ** If isContinuation is zero, then the main prompt should be used. 719: ** 720: ** If zPrior is not NULL then it is a buffer from a prior call to this 721: ** routine that can be reused. 722: ** 723: ** The result is stored in space obtained from malloc() and must either 724: ** be freed by the caller or else passed back into this routine via the 725: ** zPrior argument for reuse. 1.2 misho 726: */ 1.4 misho 727: static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ 1.2 misho 728: char *zPrompt; 729: char *zResult; 730: if( in!=0 ){ 1.4 misho 731: zResult = local_getline(zPrior, in); 1.2 misho 732: }else{ 1.4 misho 733: zPrompt = isContinuation ? continuePrompt : mainPrompt; 734: #if SHELL_USE_LOCAL_GETLINE 735: printf("%s", zPrompt); 736: fflush(stdout); 737: zResult = local_getline(zPrior, stdin); 738: #else 739: free(zPrior); 740: zResult = shell_readline(zPrompt); 741: if( zResult && *zResult ) shell_add_history(zResult); 742: #endif 1.2 misho 743: } 744: return zResult; 745: } 746: 1.5 ! misho 747: 1.4 misho 748: /* 1.5 ! misho 749: ** Return the value of a hexadecimal digit. Return -1 if the input ! 750: ** is not a hex digit. 1.4 misho 751: */ 1.5 ! misho 752: static int hexDigitValue(char c){ ! 753: if( c>='0' && c<='9' ) return c - '0'; ! 754: if( c>='a' && c<='f' ) return c - 'a' + 10; ! 755: if( c>='A' && c<='F' ) return c - 'A' + 10; ! 756: return -1; ! 757: } 1.4 misho 758: 759: /* 1.5 ! misho 760: ** Interpret zArg as an integer value, possibly with suffixes. 1.4 misho 761: */ 1.5 ! misho 762: static sqlite3_int64 integerValue(const char *zArg){ ! 763: sqlite3_int64 v = 0; ! 764: static const struct { char *zSuffix; int iMult; } aMult[] = { ! 765: { "KiB", 1024 }, ! 766: { "MiB", 1024*1024 }, ! 767: { "GiB", 1024*1024*1024 }, ! 768: { "KB", 1000 }, ! 769: { "MB", 1000000 }, ! 770: { "GB", 1000000000 }, ! 771: { "K", 1000 }, ! 772: { "M", 1000000 }, ! 773: { "G", 1000000000 }, ! 774: }; ! 775: int i; ! 776: int isNeg = 0; ! 777: if( zArg[0]=='-' ){ ! 778: isNeg = 1; ! 779: zArg++; ! 780: }else if( zArg[0]=='+' ){ ! 781: zArg++; ! 782: } ! 783: if( zArg[0]=='0' && zArg[1]=='x' ){ ! 784: int x; ! 785: zArg += 2; ! 786: while( (x = hexDigitValue(zArg[0]))>=0 ){ ! 787: v = (v<<4) + x; ! 788: zArg++; ! 789: } ! 790: }else{ ! 791: while( IsDigit(zArg[0]) ){ ! 792: v = v*10 + zArg[0] - '0'; ! 793: zArg++; ! 794: } ! 795: } ! 796: for(i=0; i<ArraySize(aMult); i++){ ! 797: if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ ! 798: v *= aMult[i].iMult; ! 799: break; ! 800: } ! 801: } ! 802: return isNeg? -v : v; ! 803: } 1.2 misho 804: 805: /* 1.5 ! misho 806: ** A variable length string to which one can append text. 1.2 misho 807: */ 1.5 ! misho 808: typedef struct ShellText ShellText; ! 809: struct ShellText { ! 810: char *z; ! 811: int n; ! 812: int nAlloc; 1.2 misho 813: }; 814: 815: /* 1.5 ! misho 816: ** Initialize and destroy a ShellText object 1.4 misho 817: */ 1.5 ! misho 818: static void initText(ShellText *p){ ! 819: memset(p, 0, sizeof(*p)); ! 820: } ! 821: static void freeText(ShellText *p){ ! 822: free(p->z); ! 823: initText(p); ! 824: } 1.4 misho 825: 1.5 ! misho 826: /* zIn is either a pointer to a NULL-terminated string in memory obtained ! 827: ** from malloc(), or a NULL pointer. The string pointed to by zAppend is ! 828: ** added to zIn, and the result returned in memory obtained from malloc(). ! 829: ** zIn, if it was not NULL, is freed. ! 830: ** ! 831: ** If the third argument, quote, is not '\0', then it is used as a ! 832: ** quote character for zAppend. 1.2 misho 833: */ 1.5 ! misho 834: static void appendText(ShellText *p, char const *zAppend, char quote){ ! 835: int len; ! 836: int i; ! 837: int nAppend = strlen30(zAppend); ! 838: ! 839: len = nAppend+p->n+1; ! 840: if( quote ){ ! 841: len += 2; ! 842: for(i=0; i<nAppend; i++){ ! 843: if( zAppend[i]==quote ) len++; ! 844: } ! 845: } 1.2 misho 846: 1.5 ! misho 847: if( p->n+len>=p->nAlloc ){ ! 848: p->nAlloc = p->nAlloc*2 + len + 20; ! 849: p->z = realloc(p->z, p->nAlloc); ! 850: if( p->z==0 ) shell_out_of_memory(); ! 851: } 1.2 misho 852: 1.5 ! misho 853: if( quote ){ ! 854: char *zCsr = p->z+p->n; ! 855: *zCsr++ = quote; ! 856: for(i=0; i<nAppend; i++){ ! 857: *zCsr++ = zAppend[i]; ! 858: if( zAppend[i]==quote ) *zCsr++ = quote; ! 859: } ! 860: *zCsr++ = quote; ! 861: p->n = (int)(zCsr - p->z); ! 862: *zCsr = '\0'; ! 863: }else{ ! 864: memcpy(p->z+p->n, zAppend, nAppend); ! 865: p->n += nAppend; ! 866: p->z[p->n] = '\0'; ! 867: } ! 868: } 1.2 misho 869: 870: /* 1.5 ! misho 871: ** Attempt to determine if identifier zName needs to be quoted, either ! 872: ** because it contains non-alphanumeric characters, or because it is an ! 873: ** SQLite keyword. Be conservative in this estimate: When in doubt assume ! 874: ** that quoting is required. ! 875: ** ! 876: ** Return '"' if quoting is required. Return 0 if no quoting is required. 1.2 misho 877: */ 1.5 ! misho 878: static char quoteChar(const char *zName){ ! 879: int i; ! 880: if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; ! 881: for(i=0; zName[i]; i++){ ! 882: if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; ! 883: } ! 884: return sqlite3_keyword_check(zName, i) ? '"' : 0; ! 885: } 1.2 misho 886: 887: /* 1.5 ! misho 888: ** Construct a fake object name and column list to describe the structure ! 889: ** of the view, virtual table, or table valued function zSchema.zName. 1.2 misho 890: */ 1.5 ! misho 891: static char *shellFakeSchema( ! 892: sqlite3 *db, /* The database connection containing the vtab */ ! 893: const char *zSchema, /* Schema of the database holding the vtab */ ! 894: const char *zName /* The name of the virtual table */ ! 895: ){ ! 896: sqlite3_stmt *pStmt = 0; ! 897: char *zSql; ! 898: ShellText s; ! 899: char cQuote; ! 900: char *zDiv = "("; ! 901: int nRow = 0; ! 902: ! 903: zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", ! 904: zSchema ? zSchema : "main", zName); ! 905: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ! 906: sqlite3_free(zSql); ! 907: initText(&s); ! 908: if( zSchema ){ ! 909: cQuote = quoteChar(zSchema); ! 910: if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; ! 911: appendText(&s, zSchema, cQuote); ! 912: appendText(&s, ".", 0); ! 913: } ! 914: cQuote = quoteChar(zName); ! 915: appendText(&s, zName, cQuote); ! 916: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 917: const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); ! 918: nRow++; ! 919: appendText(&s, zDiv, 0); ! 920: zDiv = ","; ! 921: cQuote = quoteChar(zCol); ! 922: appendText(&s, zCol, cQuote); ! 923: } ! 924: appendText(&s, ")", 0); ! 925: sqlite3_finalize(pStmt); ! 926: if( nRow==0 ){ ! 927: freeText(&s); ! 928: s.z = 0; ! 929: } ! 930: return s.z; 1.2 misho 931: } 932: 933: /* 1.5 ! misho 934: ** SQL function: shell_module_schema(X) ! 935: ** ! 936: ** Return a fake schema for the table-valued function or eponymous virtual ! 937: ** table X. 1.2 misho 938: */ 1.5 ! misho 939: static void shellModuleSchema( ! 940: sqlite3_context *pCtx, ! 941: int nVal, ! 942: sqlite3_value **apVal ! 943: ){ ! 944: const char *zName = (const char*)sqlite3_value_text(apVal[0]); ! 945: char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); ! 946: UNUSED_PARAMETER(nVal); ! 947: if( zFake ){ ! 948: sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), ! 949: -1, sqlite3_free); ! 950: free(zFake); ! 951: } 1.2 misho 952: } 953: 954: /* 1.5 ! misho 955: ** SQL function: shell_add_schema(S,X) ! 956: ** ! 957: ** Add the schema name X to the CREATE statement in S and return the result. ! 958: ** Examples: ! 959: ** ! 960: ** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x); ! 961: ** ! 962: ** Also works on ! 963: ** ! 964: ** CREATE INDEX ! 965: ** CREATE UNIQUE INDEX ! 966: ** CREATE VIEW ! 967: ** CREATE TRIGGER ! 968: ** CREATE VIRTUAL TABLE ! 969: ** ! 970: ** This UDF is used by the .schema command to insert the schema name of ! 971: ** attached databases into the middle of the sqlite_schema.sql field. 1.2 misho 972: */ 1.5 ! misho 973: static void shellAddSchemaName( ! 974: sqlite3_context *pCtx, ! 975: int nVal, ! 976: sqlite3_value **apVal ! 977: ){ ! 978: static const char *aPrefix[] = { ! 979: "TABLE", ! 980: "INDEX", ! 981: "UNIQUE INDEX", ! 982: "VIEW", ! 983: "TRIGGER", ! 984: "VIRTUAL TABLE" ! 985: }; ! 986: int i = 0; ! 987: const char *zIn = (const char*)sqlite3_value_text(apVal[0]); ! 988: const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); ! 989: const char *zName = (const char*)sqlite3_value_text(apVal[2]); ! 990: sqlite3 *db = sqlite3_context_db_handle(pCtx); ! 991: UNUSED_PARAMETER(nVal); ! 992: if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ ! 993: for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){ ! 994: int n = strlen30(aPrefix[i]); ! 995: if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ ! 996: char *z = 0; ! 997: char *zFake = 0; ! 998: if( zSchema ){ ! 999: char cQuote = quoteChar(zSchema); ! 1000: if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ ! 1001: z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); ! 1002: }else{ ! 1003: z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); ! 1004: } ! 1005: } ! 1006: if( zName ! 1007: && aPrefix[i][0]=='V' ! 1008: && (zFake = shellFakeSchema(db, zSchema, zName))!=0 ! 1009: ){ ! 1010: if( z==0 ){ ! 1011: z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake); ! 1012: }else{ ! 1013: z = sqlite3_mprintf("%z\n/* %s */", z, zFake); ! 1014: } ! 1015: free(zFake); ! 1016: } ! 1017: if( z ){ ! 1018: sqlite3_result_text(pCtx, z, -1, sqlite3_free); ! 1019: return; ! 1020: } 1.2 misho 1021: } 1022: } 1023: } 1.5 ! misho 1024: sqlite3_result_value(pCtx, apVal[0]); 1.2 misho 1025: } 1026: 1027: /* 1.5 ! misho 1028: ** The source code for several run-time loadable extensions is inserted ! 1029: ** below by the ../tool/mkshellc.tcl script. Before processing that included ! 1030: ** code, we need to override some macros to make the included program code ! 1031: ** work here in the middle of this regular program. ! 1032: */ ! 1033: #define SQLITE_EXTENSION_INIT1 ! 1034: #define SQLITE_EXTENSION_INIT2(X) (void)(X) ! 1035: ! 1036: #if defined(_WIN32) && defined(_MSC_VER) ! 1037: /************************* Begin test_windirent.h ******************/ ! 1038: /* ! 1039: ** 2015 November 30 ! 1040: ** ! 1041: ** The author disclaims copyright to this source code. In place of ! 1042: ** a legal notice, here is a blessing: ! 1043: ** ! 1044: ** May you do good and not evil. ! 1045: ** May you find forgiveness for yourself and forgive others. ! 1046: ** May you share freely, never taking more than you give. ! 1047: ** ! 1048: ************************************************************************* ! 1049: ** This file contains declarations for most of the opendir() family of ! 1050: ** POSIX functions on Win32 using the MSVCRT. ! 1051: */ ! 1052: ! 1053: #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) ! 1054: #define SQLITE_WINDIRENT_H ! 1055: ! 1056: /* ! 1057: ** We need several data types from the Windows SDK header. ! 1058: */ ! 1059: ! 1060: #ifndef WIN32_LEAN_AND_MEAN ! 1061: #define WIN32_LEAN_AND_MEAN ! 1062: #endif ! 1063: ! 1064: #include "windows.h" ! 1065: ! 1066: /* ! 1067: ** We need several support functions from the SQLite core. 1.2 misho 1068: */ 1.5 ! misho 1069: ! 1070: /* #include "sqlite3.h" */ 1.2 misho 1071: 1072: /* 1.5 ! misho 1073: ** We need several things from the ANSI and MSVCRT headers. 1.2 misho 1074: */ 1.5 ! misho 1075: ! 1076: #include <stdio.h> ! 1077: #include <stdlib.h> ! 1078: #include <errno.h> ! 1079: #include <io.h> ! 1080: #include <limits.h> ! 1081: #include <sys/types.h> ! 1082: #include <sys/stat.h> 1.2 misho 1083: 1084: /* 1.5 ! misho 1085: ** We may need several defines that should have been in "sys/stat.h". 1.2 misho 1086: */ 1.5 ! misho 1087: ! 1088: #ifndef S_ISREG ! 1089: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) ! 1090: #endif ! 1091: ! 1092: #ifndef S_ISDIR ! 1093: #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) ! 1094: #endif ! 1095: ! 1096: #ifndef S_ISLNK ! 1097: #define S_ISLNK(mode) (0) ! 1098: #endif 1.2 misho 1099: 1100: /* 1.5 ! misho 1101: ** We may need to provide the "mode_t" type. 1.2 misho 1102: */ 1103: 1.5 ! misho 1104: #ifndef MODE_T_DEFINED ! 1105: #define MODE_T_DEFINED ! 1106: typedef unsigned short mode_t; ! 1107: #endif ! 1108: 1.2 misho 1109: /* 1.5 ! misho 1110: ** We may need to provide the "ino_t" type. 1.2 misho 1111: */ 1.5 ! misho 1112: ! 1113: #ifndef INO_T_DEFINED ! 1114: #define INO_T_DEFINED ! 1115: typedef unsigned short ino_t; 1.2 misho 1116: #endif 1117: 1118: /* 1.5 ! misho 1119: ** We need to define "NAME_MAX" if it was not present in "limits.h". 1.4 misho 1120: */ 1.5 ! misho 1121: ! 1122: #ifndef NAME_MAX ! 1123: # ifdef FILENAME_MAX ! 1124: # define NAME_MAX (FILENAME_MAX) ! 1125: # else ! 1126: # define NAME_MAX (260) ! 1127: # endif ! 1128: #endif 1.4 misho 1129: 1130: /* 1.5 ! misho 1131: ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". 1.2 misho 1132: */ 1133: 1.5 ! misho 1134: #ifndef NULL_INTPTR_T ! 1135: # define NULL_INTPTR_T ((intptr_t)(0)) ! 1136: #endif ! 1137: ! 1138: #ifndef BAD_INTPTR_T ! 1139: # define BAD_INTPTR_T ((intptr_t)(-1)) ! 1140: #endif ! 1141: ! 1142: /* ! 1143: ** We need to provide the necessary structures and related types. ! 1144: */ ! 1145: ! 1146: #ifndef DIRENT_DEFINED ! 1147: #define DIRENT_DEFINED ! 1148: typedef struct DIRENT DIRENT; ! 1149: typedef DIRENT *LPDIRENT; ! 1150: struct DIRENT { ! 1151: ino_t d_ino; /* Sequence number, do not use. */ ! 1152: unsigned d_attributes; /* Win32 file attributes. */ ! 1153: char d_name[NAME_MAX + 1]; /* Name within the directory. */ ! 1154: }; ! 1155: #endif ! 1156: ! 1157: #ifndef DIR_DEFINED ! 1158: #define DIR_DEFINED ! 1159: typedef struct DIR DIR; ! 1160: typedef DIR *LPDIR; ! 1161: struct DIR { ! 1162: intptr_t d_handle; /* Value returned by "_findfirst". */ ! 1163: DIRENT d_first; /* DIRENT constructed based on "_findfirst". */ ! 1164: DIRENT d_next; /* DIRENT constructed based on "_findnext". */ ! 1165: }; ! 1166: #endif ! 1167: ! 1168: /* ! 1169: ** Provide a macro, for use by the implementation, to determine if a ! 1170: ** particular directory entry should be skipped over when searching for ! 1171: ** the next directory entry that should be returned by the readdir() or ! 1172: ** readdir_r() functions. ! 1173: */ ! 1174: ! 1175: #ifndef is_filtered ! 1176: # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) ! 1177: #endif ! 1178: ! 1179: /* ! 1180: ** Provide the function prototype for the POSIX compatiable getenv() ! 1181: ** function. This function is not thread-safe. ! 1182: */ ! 1183: ! 1184: extern const char *windirent_getenv(const char *name); ! 1185: ! 1186: /* ! 1187: ** Finally, we can provide the function prototypes for the opendir(), ! 1188: ** readdir(), readdir_r(), and closedir() POSIX functions. ! 1189: */ ! 1190: ! 1191: extern LPDIR opendir(const char *dirname); ! 1192: extern LPDIRENT readdir(LPDIR dirp); ! 1193: extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); ! 1194: extern INT closedir(LPDIR dirp); ! 1195: ! 1196: #endif /* defined(WIN32) && defined(_MSC_VER) */ ! 1197: ! 1198: /************************* End test_windirent.h ********************/ ! 1199: /************************* Begin test_windirent.c ******************/ ! 1200: /* ! 1201: ** 2015 November 30 ! 1202: ** ! 1203: ** The author disclaims copyright to this source code. In place of ! 1204: ** a legal notice, here is a blessing: ! 1205: ** ! 1206: ** May you do good and not evil. ! 1207: ** May you find forgiveness for yourself and forgive others. ! 1208: ** May you share freely, never taking more than you give. ! 1209: ** ! 1210: ************************************************************************* ! 1211: ** This file contains code to implement most of the opendir() family of ! 1212: ** POSIX functions on Win32 using the MSVCRT. ! 1213: */ ! 1214: ! 1215: #if defined(_WIN32) && defined(_MSC_VER) ! 1216: /* #include "test_windirent.h" */ ! 1217: ! 1218: /* ! 1219: ** Implementation of the POSIX getenv() function using the Win32 API. ! 1220: ** This function is not thread-safe. ! 1221: */ ! 1222: const char *windirent_getenv( ! 1223: const char *name ! 1224: ){ ! 1225: static char value[32768]; /* Maximum length, per MSDN */ ! 1226: DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */ ! 1227: DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */ ! 1228: ! 1229: memset(value, 0, sizeof(value)); ! 1230: dwRet = GetEnvironmentVariableA(name, value, dwSize); ! 1231: if( dwRet==0 || dwRet>dwSize ){ ! 1232: /* ! 1233: ** The function call to GetEnvironmentVariableA() failed -OR- ! 1234: ** the buffer is not large enough. Either way, return NULL. ! 1235: */ ! 1236: return 0; ! 1237: }else{ ! 1238: /* ! 1239: ** The function call to GetEnvironmentVariableA() succeeded ! 1240: ** -AND- the buffer contains the entire value. ! 1241: */ ! 1242: return value; ! 1243: } ! 1244: } ! 1245: ! 1246: /* ! 1247: ** Implementation of the POSIX opendir() function using the MSVCRT. ! 1248: */ ! 1249: LPDIR opendir( ! 1250: const char *dirname ! 1251: ){ ! 1252: struct _finddata_t data; ! 1253: LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); ! 1254: SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); ! 1255: ! 1256: if( dirp==NULL ) return NULL; ! 1257: memset(dirp, 0, sizeof(DIR)); ! 1258: ! 1259: /* TODO: Remove this if Unix-style root paths are not used. */ ! 1260: if( sqlite3_stricmp(dirname, "/")==0 ){ ! 1261: dirname = windirent_getenv("SystemDrive"); ! 1262: } ! 1263: ! 1264: memset(&data, 0, sizeof(struct _finddata_t)); ! 1265: _snprintf(data.name, namesize, "%s\\*", dirname); ! 1266: dirp->d_handle = _findfirst(data.name, &data); ! 1267: ! 1268: if( dirp->d_handle==BAD_INTPTR_T ){ ! 1269: closedir(dirp); ! 1270: return NULL; ! 1271: } ! 1272: ! 1273: /* TODO: Remove this block to allow hidden and/or system files. */ ! 1274: if( is_filtered(data) ){ ! 1275: next: ! 1276: ! 1277: memset(&data, 0, sizeof(struct _finddata_t)); ! 1278: if( _findnext(dirp->d_handle, &data)==-1 ){ ! 1279: closedir(dirp); ! 1280: return NULL; ! 1281: } ! 1282: ! 1283: /* TODO: Remove this block to allow hidden and/or system files. */ ! 1284: if( is_filtered(data) ) goto next; ! 1285: } ! 1286: ! 1287: dirp->d_first.d_attributes = data.attrib; ! 1288: strncpy(dirp->d_first.d_name, data.name, NAME_MAX); ! 1289: dirp->d_first.d_name[NAME_MAX] = '\0'; ! 1290: ! 1291: return dirp; ! 1292: } ! 1293: ! 1294: /* ! 1295: ** Implementation of the POSIX readdir() function using the MSVCRT. ! 1296: */ ! 1297: LPDIRENT readdir( ! 1298: LPDIR dirp ! 1299: ){ ! 1300: struct _finddata_t data; ! 1301: ! 1302: if( dirp==NULL ) return NULL; ! 1303: ! 1304: if( dirp->d_first.d_ino==0 ){ ! 1305: dirp->d_first.d_ino++; ! 1306: dirp->d_next.d_ino++; ! 1307: ! 1308: return &dirp->d_first; ! 1309: } ! 1310: ! 1311: next: ! 1312: ! 1313: memset(&data, 0, sizeof(struct _finddata_t)); ! 1314: if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; ! 1315: ! 1316: /* TODO: Remove this block to allow hidden and/or system files. */ ! 1317: if( is_filtered(data) ) goto next; ! 1318: ! 1319: dirp->d_next.d_ino++; ! 1320: dirp->d_next.d_attributes = data.attrib; ! 1321: strncpy(dirp->d_next.d_name, data.name, NAME_MAX); ! 1322: dirp->d_next.d_name[NAME_MAX] = '\0'; ! 1323: ! 1324: return &dirp->d_next; ! 1325: } ! 1326: ! 1327: /* ! 1328: ** Implementation of the POSIX readdir_r() function using the MSVCRT. ! 1329: */ ! 1330: INT readdir_r( ! 1331: LPDIR dirp, ! 1332: LPDIRENT entry, ! 1333: LPDIRENT *result ! 1334: ){ ! 1335: struct _finddata_t data; ! 1336: ! 1337: if( dirp==NULL ) return EBADF; ! 1338: ! 1339: if( dirp->d_first.d_ino==0 ){ ! 1340: dirp->d_first.d_ino++; ! 1341: dirp->d_next.d_ino++; ! 1342: ! 1343: entry->d_ino = dirp->d_first.d_ino; ! 1344: entry->d_attributes = dirp->d_first.d_attributes; ! 1345: strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); ! 1346: entry->d_name[NAME_MAX] = '\0'; ! 1347: ! 1348: *result = entry; ! 1349: return 0; ! 1350: } ! 1351: ! 1352: next: ! 1353: ! 1354: memset(&data, 0, sizeof(struct _finddata_t)); ! 1355: if( _findnext(dirp->d_handle, &data)==-1 ){ ! 1356: *result = NULL; ! 1357: return ENOENT; ! 1358: } ! 1359: ! 1360: /* TODO: Remove this block to allow hidden and/or system files. */ ! 1361: if( is_filtered(data) ) goto next; ! 1362: ! 1363: entry->d_ino = (ino_t)-1; /* not available */ ! 1364: entry->d_attributes = data.attrib; ! 1365: strncpy(entry->d_name, data.name, NAME_MAX); ! 1366: entry->d_name[NAME_MAX] = '\0'; ! 1367: ! 1368: *result = entry; ! 1369: return 0; ! 1370: } ! 1371: ! 1372: /* ! 1373: ** Implementation of the POSIX closedir() function using the MSVCRT. ! 1374: */ ! 1375: INT closedir( ! 1376: LPDIR dirp ! 1377: ){ ! 1378: INT result = 0; ! 1379: ! 1380: if( dirp==NULL ) return EINVAL; ! 1381: ! 1382: if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ ! 1383: result = _findclose(dirp->d_handle); ! 1384: } ! 1385: ! 1386: sqlite3_free(dirp); ! 1387: return result; ! 1388: } ! 1389: ! 1390: #endif /* defined(WIN32) && defined(_MSC_VER) */ ! 1391: ! 1392: /************************* End test_windirent.c ********************/ ! 1393: #define dirent DIRENT ! 1394: #endif ! 1395: /************************* Begin ../ext/misc/shathree.c ******************/ ! 1396: /* ! 1397: ** 2017-03-08 ! 1398: ** ! 1399: ** The author disclaims copyright to this source code. In place of ! 1400: ** a legal notice, here is a blessing: ! 1401: ** ! 1402: ** May you do good and not evil. ! 1403: ** May you find forgiveness for yourself and forgive others. ! 1404: ** May you share freely, never taking more than you give. ! 1405: ** ! 1406: ****************************************************************************** ! 1407: ** ! 1408: ** This SQLite extension implements functions that compute SHA3 hashes. ! 1409: ** Two SQL functions are implemented: ! 1410: ** ! 1411: ** sha3(X,SIZE) ! 1412: ** sha3_query(Y,SIZE) ! 1413: ** ! 1414: ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if ! 1415: ** X is NULL. ! 1416: ** ! 1417: ** The sha3_query(Y) function evalutes all queries in the SQL statements of Y ! 1418: ** and returns a hash of their results. ! 1419: ** ! 1420: ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm ! 1421: ** is used. If SIZE is included it must be one of the integers 224, 256, ! 1422: ** 384, or 512, to determine SHA3 hash variant that is computed. ! 1423: */ ! 1424: /* #include "sqlite3ext.h" */ ! 1425: SQLITE_EXTENSION_INIT1 ! 1426: #include <assert.h> ! 1427: #include <string.h> ! 1428: #include <stdarg.h> ! 1429: /* typedef sqlite3_uint64 u64; */ ! 1430: ! 1431: /****************************************************************************** ! 1432: ** The Hash Engine ! 1433: */ ! 1434: /* ! 1435: ** Macros to determine whether the machine is big or little endian, ! 1436: ** and whether or not that determination is run-time or compile-time. ! 1437: ** ! 1438: ** For best performance, an attempt is made to guess at the byte-order ! 1439: ** using C-preprocessor macros. If that is unsuccessful, or if ! 1440: ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined ! 1441: ** at run-time. ! 1442: */ ! 1443: #ifndef SHA3_BYTEORDER ! 1444: # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ ! 1445: defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ ! 1446: defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ ! 1447: defined(__arm__) ! 1448: # define SHA3_BYTEORDER 1234 ! 1449: # elif defined(sparc) || defined(__ppc__) ! 1450: # define SHA3_BYTEORDER 4321 ! 1451: # else ! 1452: # define SHA3_BYTEORDER 0 ! 1453: # endif ! 1454: #endif ! 1455: ! 1456: ! 1457: /* ! 1458: ** State structure for a SHA3 hash in progress ! 1459: */ ! 1460: typedef struct SHA3Context SHA3Context; ! 1461: struct SHA3Context { ! 1462: union { ! 1463: u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ ! 1464: unsigned char x[1600]; /* ... or 1600 bytes */ ! 1465: } u; ! 1466: unsigned nRate; /* Bytes of input accepted per Keccak iteration */ ! 1467: unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ ! 1468: unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ ! 1469: }; ! 1470: ! 1471: /* ! 1472: ** A single step of the Keccak mixing function for a 1600-bit state ! 1473: */ ! 1474: static void KeccakF1600Step(SHA3Context *p){ ! 1475: int i; ! 1476: u64 b0, b1, b2, b3, b4; ! 1477: u64 c0, c1, c2, c3, c4; ! 1478: u64 d0, d1, d2, d3, d4; ! 1479: static const u64 RC[] = { ! 1480: 0x0000000000000001ULL, 0x0000000000008082ULL, ! 1481: 0x800000000000808aULL, 0x8000000080008000ULL, ! 1482: 0x000000000000808bULL, 0x0000000080000001ULL, ! 1483: 0x8000000080008081ULL, 0x8000000000008009ULL, ! 1484: 0x000000000000008aULL, 0x0000000000000088ULL, ! 1485: 0x0000000080008009ULL, 0x000000008000000aULL, ! 1486: 0x000000008000808bULL, 0x800000000000008bULL, ! 1487: 0x8000000000008089ULL, 0x8000000000008003ULL, ! 1488: 0x8000000000008002ULL, 0x8000000000000080ULL, ! 1489: 0x000000000000800aULL, 0x800000008000000aULL, ! 1490: 0x8000000080008081ULL, 0x8000000000008080ULL, ! 1491: 0x0000000080000001ULL, 0x8000000080008008ULL ! 1492: }; ! 1493: # define a00 (p->u.s[0]) ! 1494: # define a01 (p->u.s[1]) ! 1495: # define a02 (p->u.s[2]) ! 1496: # define a03 (p->u.s[3]) ! 1497: # define a04 (p->u.s[4]) ! 1498: # define a10 (p->u.s[5]) ! 1499: # define a11 (p->u.s[6]) ! 1500: # define a12 (p->u.s[7]) ! 1501: # define a13 (p->u.s[8]) ! 1502: # define a14 (p->u.s[9]) ! 1503: # define a20 (p->u.s[10]) ! 1504: # define a21 (p->u.s[11]) ! 1505: # define a22 (p->u.s[12]) ! 1506: # define a23 (p->u.s[13]) ! 1507: # define a24 (p->u.s[14]) ! 1508: # define a30 (p->u.s[15]) ! 1509: # define a31 (p->u.s[16]) ! 1510: # define a32 (p->u.s[17]) ! 1511: # define a33 (p->u.s[18]) ! 1512: # define a34 (p->u.s[19]) ! 1513: # define a40 (p->u.s[20]) ! 1514: # define a41 (p->u.s[21]) ! 1515: # define a42 (p->u.s[22]) ! 1516: # define a43 (p->u.s[23]) ! 1517: # define a44 (p->u.s[24]) ! 1518: # define ROL64(a,x) ((a<<x)|(a>>(64-x))) ! 1519: ! 1520: for(i=0; i<24; i+=4){ ! 1521: c0 = a00^a10^a20^a30^a40; ! 1522: c1 = a01^a11^a21^a31^a41; ! 1523: c2 = a02^a12^a22^a32^a42; ! 1524: c3 = a03^a13^a23^a33^a43; ! 1525: c4 = a04^a14^a24^a34^a44; ! 1526: d0 = c4^ROL64(c1, 1); ! 1527: d1 = c0^ROL64(c2, 1); ! 1528: d2 = c1^ROL64(c3, 1); ! 1529: d3 = c2^ROL64(c4, 1); ! 1530: d4 = c3^ROL64(c0, 1); ! 1531: ! 1532: b0 = (a00^d0); ! 1533: b1 = ROL64((a11^d1), 44); ! 1534: b2 = ROL64((a22^d2), 43); ! 1535: b3 = ROL64((a33^d3), 21); ! 1536: b4 = ROL64((a44^d4), 14); ! 1537: a00 = b0 ^((~b1)& b2 ); ! 1538: a00 ^= RC[i]; ! 1539: a11 = b1 ^((~b2)& b3 ); ! 1540: a22 = b2 ^((~b3)& b4 ); ! 1541: a33 = b3 ^((~b4)& b0 ); ! 1542: a44 = b4 ^((~b0)& b1 ); ! 1543: ! 1544: b2 = ROL64((a20^d0), 3); ! 1545: b3 = ROL64((a31^d1), 45); ! 1546: b4 = ROL64((a42^d2), 61); ! 1547: b0 = ROL64((a03^d3), 28); ! 1548: b1 = ROL64((a14^d4), 20); ! 1549: a20 = b0 ^((~b1)& b2 ); ! 1550: a31 = b1 ^((~b2)& b3 ); ! 1551: a42 = b2 ^((~b3)& b4 ); ! 1552: a03 = b3 ^((~b4)& b0 ); ! 1553: a14 = b4 ^((~b0)& b1 ); ! 1554: ! 1555: b4 = ROL64((a40^d0), 18); ! 1556: b0 = ROL64((a01^d1), 1); ! 1557: b1 = ROL64((a12^d2), 6); ! 1558: b2 = ROL64((a23^d3), 25); ! 1559: b3 = ROL64((a34^d4), 8); ! 1560: a40 = b0 ^((~b1)& b2 ); ! 1561: a01 = b1 ^((~b2)& b3 ); ! 1562: a12 = b2 ^((~b3)& b4 ); ! 1563: a23 = b3 ^((~b4)& b0 ); ! 1564: a34 = b4 ^((~b0)& b1 ); ! 1565: ! 1566: b1 = ROL64((a10^d0), 36); ! 1567: b2 = ROL64((a21^d1), 10); ! 1568: b3 = ROL64((a32^d2), 15); ! 1569: b4 = ROL64((a43^d3), 56); ! 1570: b0 = ROL64((a04^d4), 27); ! 1571: a10 = b0 ^((~b1)& b2 ); ! 1572: a21 = b1 ^((~b2)& b3 ); ! 1573: a32 = b2 ^((~b3)& b4 ); ! 1574: a43 = b3 ^((~b4)& b0 ); ! 1575: a04 = b4 ^((~b0)& b1 ); ! 1576: ! 1577: b3 = ROL64((a30^d0), 41); ! 1578: b4 = ROL64((a41^d1), 2); ! 1579: b0 = ROL64((a02^d2), 62); ! 1580: b1 = ROL64((a13^d3), 55); ! 1581: b2 = ROL64((a24^d4), 39); ! 1582: a30 = b0 ^((~b1)& b2 ); ! 1583: a41 = b1 ^((~b2)& b3 ); ! 1584: a02 = b2 ^((~b3)& b4 ); ! 1585: a13 = b3 ^((~b4)& b0 ); ! 1586: a24 = b4 ^((~b0)& b1 ); ! 1587: ! 1588: c0 = a00^a20^a40^a10^a30; ! 1589: c1 = a11^a31^a01^a21^a41; ! 1590: c2 = a22^a42^a12^a32^a02; ! 1591: c3 = a33^a03^a23^a43^a13; ! 1592: c4 = a44^a14^a34^a04^a24; ! 1593: d0 = c4^ROL64(c1, 1); ! 1594: d1 = c0^ROL64(c2, 1); ! 1595: d2 = c1^ROL64(c3, 1); ! 1596: d3 = c2^ROL64(c4, 1); ! 1597: d4 = c3^ROL64(c0, 1); ! 1598: ! 1599: b0 = (a00^d0); ! 1600: b1 = ROL64((a31^d1), 44); ! 1601: b2 = ROL64((a12^d2), 43); ! 1602: b3 = ROL64((a43^d3), 21); ! 1603: b4 = ROL64((a24^d4), 14); ! 1604: a00 = b0 ^((~b1)& b2 ); ! 1605: a00 ^= RC[i+1]; ! 1606: a31 = b1 ^((~b2)& b3 ); ! 1607: a12 = b2 ^((~b3)& b4 ); ! 1608: a43 = b3 ^((~b4)& b0 ); ! 1609: a24 = b4 ^((~b0)& b1 ); ! 1610: ! 1611: b2 = ROL64((a40^d0), 3); ! 1612: b3 = ROL64((a21^d1), 45); ! 1613: b4 = ROL64((a02^d2), 61); ! 1614: b0 = ROL64((a33^d3), 28); ! 1615: b1 = ROL64((a14^d4), 20); ! 1616: a40 = b0 ^((~b1)& b2 ); ! 1617: a21 = b1 ^((~b2)& b3 ); ! 1618: a02 = b2 ^((~b3)& b4 ); ! 1619: a33 = b3 ^((~b4)& b0 ); ! 1620: a14 = b4 ^((~b0)& b1 ); ! 1621: ! 1622: b4 = ROL64((a30^d0), 18); ! 1623: b0 = ROL64((a11^d1), 1); ! 1624: b1 = ROL64((a42^d2), 6); ! 1625: b2 = ROL64((a23^d3), 25); ! 1626: b3 = ROL64((a04^d4), 8); ! 1627: a30 = b0 ^((~b1)& b2 ); ! 1628: a11 = b1 ^((~b2)& b3 ); ! 1629: a42 = b2 ^((~b3)& b4 ); ! 1630: a23 = b3 ^((~b4)& b0 ); ! 1631: a04 = b4 ^((~b0)& b1 ); ! 1632: ! 1633: b1 = ROL64((a20^d0), 36); ! 1634: b2 = ROL64((a01^d1), 10); ! 1635: b3 = ROL64((a32^d2), 15); ! 1636: b4 = ROL64((a13^d3), 56); ! 1637: b0 = ROL64((a44^d4), 27); ! 1638: a20 = b0 ^((~b1)& b2 ); ! 1639: a01 = b1 ^((~b2)& b3 ); ! 1640: a32 = b2 ^((~b3)& b4 ); ! 1641: a13 = b3 ^((~b4)& b0 ); ! 1642: a44 = b4 ^((~b0)& b1 ); ! 1643: ! 1644: b3 = ROL64((a10^d0), 41); ! 1645: b4 = ROL64((a41^d1), 2); ! 1646: b0 = ROL64((a22^d2), 62); ! 1647: b1 = ROL64((a03^d3), 55); ! 1648: b2 = ROL64((a34^d4), 39); ! 1649: a10 = b0 ^((~b1)& b2 ); ! 1650: a41 = b1 ^((~b2)& b3 ); ! 1651: a22 = b2 ^((~b3)& b4 ); ! 1652: a03 = b3 ^((~b4)& b0 ); ! 1653: a34 = b4 ^((~b0)& b1 ); ! 1654: ! 1655: c0 = a00^a40^a30^a20^a10; ! 1656: c1 = a31^a21^a11^a01^a41; ! 1657: c2 = a12^a02^a42^a32^a22; ! 1658: c3 = a43^a33^a23^a13^a03; ! 1659: c4 = a24^a14^a04^a44^a34; ! 1660: d0 = c4^ROL64(c1, 1); ! 1661: d1 = c0^ROL64(c2, 1); ! 1662: d2 = c1^ROL64(c3, 1); ! 1663: d3 = c2^ROL64(c4, 1); ! 1664: d4 = c3^ROL64(c0, 1); ! 1665: ! 1666: b0 = (a00^d0); ! 1667: b1 = ROL64((a21^d1), 44); ! 1668: b2 = ROL64((a42^d2), 43); ! 1669: b3 = ROL64((a13^d3), 21); ! 1670: b4 = ROL64((a34^d4), 14); ! 1671: a00 = b0 ^((~b1)& b2 ); ! 1672: a00 ^= RC[i+2]; ! 1673: a21 = b1 ^((~b2)& b3 ); ! 1674: a42 = b2 ^((~b3)& b4 ); ! 1675: a13 = b3 ^((~b4)& b0 ); ! 1676: a34 = b4 ^((~b0)& b1 ); ! 1677: ! 1678: b2 = ROL64((a30^d0), 3); ! 1679: b3 = ROL64((a01^d1), 45); ! 1680: b4 = ROL64((a22^d2), 61); ! 1681: b0 = ROL64((a43^d3), 28); ! 1682: b1 = ROL64((a14^d4), 20); ! 1683: a30 = b0 ^((~b1)& b2 ); ! 1684: a01 = b1 ^((~b2)& b3 ); ! 1685: a22 = b2 ^((~b3)& b4 ); ! 1686: a43 = b3 ^((~b4)& b0 ); ! 1687: a14 = b4 ^((~b0)& b1 ); ! 1688: ! 1689: b4 = ROL64((a10^d0), 18); ! 1690: b0 = ROL64((a31^d1), 1); ! 1691: b1 = ROL64((a02^d2), 6); ! 1692: b2 = ROL64((a23^d3), 25); ! 1693: b3 = ROL64((a44^d4), 8); ! 1694: a10 = b0 ^((~b1)& b2 ); ! 1695: a31 = b1 ^((~b2)& b3 ); ! 1696: a02 = b2 ^((~b3)& b4 ); ! 1697: a23 = b3 ^((~b4)& b0 ); ! 1698: a44 = b4 ^((~b0)& b1 ); ! 1699: ! 1700: b1 = ROL64((a40^d0), 36); ! 1701: b2 = ROL64((a11^d1), 10); ! 1702: b3 = ROL64((a32^d2), 15); ! 1703: b4 = ROL64((a03^d3), 56); ! 1704: b0 = ROL64((a24^d4), 27); ! 1705: a40 = b0 ^((~b1)& b2 ); ! 1706: a11 = b1 ^((~b2)& b3 ); ! 1707: a32 = b2 ^((~b3)& b4 ); ! 1708: a03 = b3 ^((~b4)& b0 ); ! 1709: a24 = b4 ^((~b0)& b1 ); ! 1710: ! 1711: b3 = ROL64((a20^d0), 41); ! 1712: b4 = ROL64((a41^d1), 2); ! 1713: b0 = ROL64((a12^d2), 62); ! 1714: b1 = ROL64((a33^d3), 55); ! 1715: b2 = ROL64((a04^d4), 39); ! 1716: a20 = b0 ^((~b1)& b2 ); ! 1717: a41 = b1 ^((~b2)& b3 ); ! 1718: a12 = b2 ^((~b3)& b4 ); ! 1719: a33 = b3 ^((~b4)& b0 ); ! 1720: a04 = b4 ^((~b0)& b1 ); ! 1721: ! 1722: c0 = a00^a30^a10^a40^a20; ! 1723: c1 = a21^a01^a31^a11^a41; ! 1724: c2 = a42^a22^a02^a32^a12; ! 1725: c3 = a13^a43^a23^a03^a33; ! 1726: c4 = a34^a14^a44^a24^a04; ! 1727: d0 = c4^ROL64(c1, 1); ! 1728: d1 = c0^ROL64(c2, 1); ! 1729: d2 = c1^ROL64(c3, 1); ! 1730: d3 = c2^ROL64(c4, 1); ! 1731: d4 = c3^ROL64(c0, 1); ! 1732: ! 1733: b0 = (a00^d0); ! 1734: b1 = ROL64((a01^d1), 44); ! 1735: b2 = ROL64((a02^d2), 43); ! 1736: b3 = ROL64((a03^d3), 21); ! 1737: b4 = ROL64((a04^d4), 14); ! 1738: a00 = b0 ^((~b1)& b2 ); ! 1739: a00 ^= RC[i+3]; ! 1740: a01 = b1 ^((~b2)& b3 ); ! 1741: a02 = b2 ^((~b3)& b4 ); ! 1742: a03 = b3 ^((~b4)& b0 ); ! 1743: a04 = b4 ^((~b0)& b1 ); ! 1744: ! 1745: b2 = ROL64((a10^d0), 3); ! 1746: b3 = ROL64((a11^d1), 45); ! 1747: b4 = ROL64((a12^d2), 61); ! 1748: b0 = ROL64((a13^d3), 28); ! 1749: b1 = ROL64((a14^d4), 20); ! 1750: a10 = b0 ^((~b1)& b2 ); ! 1751: a11 = b1 ^((~b2)& b3 ); ! 1752: a12 = b2 ^((~b3)& b4 ); ! 1753: a13 = b3 ^((~b4)& b0 ); ! 1754: a14 = b4 ^((~b0)& b1 ); ! 1755: ! 1756: b4 = ROL64((a20^d0), 18); ! 1757: b0 = ROL64((a21^d1), 1); ! 1758: b1 = ROL64((a22^d2), 6); ! 1759: b2 = ROL64((a23^d3), 25); ! 1760: b3 = ROL64((a24^d4), 8); ! 1761: a20 = b0 ^((~b1)& b2 ); ! 1762: a21 = b1 ^((~b2)& b3 ); ! 1763: a22 = b2 ^((~b3)& b4 ); ! 1764: a23 = b3 ^((~b4)& b0 ); ! 1765: a24 = b4 ^((~b0)& b1 ); ! 1766: ! 1767: b1 = ROL64((a30^d0), 36); ! 1768: b2 = ROL64((a31^d1), 10); ! 1769: b3 = ROL64((a32^d2), 15); ! 1770: b4 = ROL64((a33^d3), 56); ! 1771: b0 = ROL64((a34^d4), 27); ! 1772: a30 = b0 ^((~b1)& b2 ); ! 1773: a31 = b1 ^((~b2)& b3 ); ! 1774: a32 = b2 ^((~b3)& b4 ); ! 1775: a33 = b3 ^((~b4)& b0 ); ! 1776: a34 = b4 ^((~b0)& b1 ); ! 1777: ! 1778: b3 = ROL64((a40^d0), 41); ! 1779: b4 = ROL64((a41^d1), 2); ! 1780: b0 = ROL64((a42^d2), 62); ! 1781: b1 = ROL64((a43^d3), 55); ! 1782: b2 = ROL64((a44^d4), 39); ! 1783: a40 = b0 ^((~b1)& b2 ); ! 1784: a41 = b1 ^((~b2)& b3 ); ! 1785: a42 = b2 ^((~b3)& b4 ); ! 1786: a43 = b3 ^((~b4)& b0 ); ! 1787: a44 = b4 ^((~b0)& b1 ); ! 1788: } ! 1789: } ! 1790: ! 1791: /* ! 1792: ** Initialize a new hash. iSize determines the size of the hash ! 1793: ** in bits and should be one of 224, 256, 384, or 512. Or iSize ! 1794: ** can be zero to use the default hash size of 256 bits. ! 1795: */ ! 1796: static void SHA3Init(SHA3Context *p, int iSize){ ! 1797: memset(p, 0, sizeof(*p)); ! 1798: if( iSize>=128 && iSize<=512 ){ ! 1799: p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; ! 1800: }else{ ! 1801: p->nRate = (1600 - 2*256)/8; ! 1802: } ! 1803: #if SHA3_BYTEORDER==1234 ! 1804: /* Known to be little-endian at compile-time. No-op */ ! 1805: #elif SHA3_BYTEORDER==4321 ! 1806: p->ixMask = 7; /* Big-endian */ ! 1807: #else ! 1808: { ! 1809: static unsigned int one = 1; ! 1810: if( 1==*(unsigned char*)&one ){ ! 1811: /* Little endian. No byte swapping. */ ! 1812: p->ixMask = 0; ! 1813: }else{ ! 1814: /* Big endian. Byte swap. */ ! 1815: p->ixMask = 7; ! 1816: } ! 1817: } ! 1818: #endif ! 1819: } ! 1820: ! 1821: /* ! 1822: ** Make consecutive calls to the SHA3Update function to add new content ! 1823: ** to the hash ! 1824: */ ! 1825: static void SHA3Update( ! 1826: SHA3Context *p, ! 1827: const unsigned char *aData, ! 1828: unsigned int nData ! 1829: ){ ! 1830: unsigned int i = 0; ! 1831: #if SHA3_BYTEORDER==1234 ! 1832: if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ ! 1833: for(; i+7<nData; i+=8){ ! 1834: p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; ! 1835: p->nLoaded += 8; ! 1836: if( p->nLoaded>=p->nRate ){ ! 1837: KeccakF1600Step(p); ! 1838: p->nLoaded = 0; 1.2 misho 1839: } 1840: } 1.5 ! misho 1841: } ! 1842: #endif ! 1843: for(; i<nData; i++){ ! 1844: #if SHA3_BYTEORDER==1234 ! 1845: p->u.x[p->nLoaded] ^= aData[i]; ! 1846: #elif SHA3_BYTEORDER==4321 ! 1847: p->u.x[p->nLoaded^0x07] ^= aData[i]; ! 1848: #else ! 1849: p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; ! 1850: #endif ! 1851: p->nLoaded++; ! 1852: if( p->nLoaded==p->nRate ){ ! 1853: KeccakF1600Step(p); ! 1854: p->nLoaded = 0; ! 1855: } ! 1856: } ! 1857: } ! 1858: ! 1859: /* ! 1860: ** After all content has been added, invoke SHA3Final() to compute ! 1861: ** the final hash. The function returns a pointer to the binary ! 1862: ** hash value. ! 1863: */ ! 1864: static unsigned char *SHA3Final(SHA3Context *p){ ! 1865: unsigned int i; ! 1866: if( p->nLoaded==p->nRate-1 ){ ! 1867: const unsigned char c1 = 0x86; ! 1868: SHA3Update(p, &c1, 1); ! 1869: }else{ ! 1870: const unsigned char c2 = 0x06; ! 1871: const unsigned char c3 = 0x80; ! 1872: SHA3Update(p, &c2, 1); ! 1873: p->nLoaded = p->nRate - 1; ! 1874: SHA3Update(p, &c3, 1); ! 1875: } ! 1876: for(i=0; i<p->nRate; i++){ ! 1877: p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; ! 1878: } ! 1879: return &p->u.x[p->nRate]; ! 1880: } ! 1881: /* End of the hashing logic ! 1882: *****************************************************************************/ ! 1883: ! 1884: /* ! 1885: ** Implementation of the sha3(X,SIZE) function. ! 1886: ** ! 1887: ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default ! 1888: ** size is 256. If X is a BLOB, it is hashed as is. ! 1889: ** For all other non-NULL types of input, X is converted into a UTF-8 string ! 1890: ** and the string is hashed without the trailing 0x00 terminator. The hash ! 1891: ** of a NULL value is NULL. ! 1892: */ ! 1893: static void sha3Func( ! 1894: sqlite3_context *context, ! 1895: int argc, ! 1896: sqlite3_value **argv ! 1897: ){ ! 1898: SHA3Context cx; ! 1899: int eType = sqlite3_value_type(argv[0]); ! 1900: int nByte = sqlite3_value_bytes(argv[0]); ! 1901: int iSize; ! 1902: if( argc==1 ){ ! 1903: iSize = 256; ! 1904: }else{ ! 1905: iSize = sqlite3_value_int(argv[1]); ! 1906: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ ! 1907: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " ! 1908: "384 512", -1); ! 1909: return; ! 1910: } ! 1911: } ! 1912: if( eType==SQLITE_NULL ) return; ! 1913: SHA3Init(&cx, iSize); ! 1914: if( eType==SQLITE_BLOB ){ ! 1915: SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); ! 1916: }else{ ! 1917: SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); ! 1918: } ! 1919: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); ! 1920: } ! 1921: ! 1922: /* Compute a string using sqlite3_vsnprintf() with a maximum length ! 1923: ** of 50 bytes and add it to the hash. ! 1924: */ ! 1925: static void hash_step_vformat( ! 1926: SHA3Context *p, /* Add content to this context */ ! 1927: const char *zFormat, ! 1928: ... ! 1929: ){ ! 1930: va_list ap; ! 1931: int n; ! 1932: char zBuf[50]; ! 1933: va_start(ap, zFormat); ! 1934: sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); ! 1935: va_end(ap); ! 1936: n = (int)strlen(zBuf); ! 1937: SHA3Update(p, (unsigned char*)zBuf, n); ! 1938: } ! 1939: ! 1940: /* ! 1941: ** Implementation of the sha3_query(SQL,SIZE) function. ! 1942: ** ! 1943: ** This function compiles and runs the SQL statement(s) given in the ! 1944: ** argument. The results are hashed using a SIZE-bit SHA3. The default ! 1945: ** size is 256. ! 1946: ** ! 1947: ** The format of the byte stream that is hashed is summarized as follows: ! 1948: ** ! 1949: ** S<n>:<sql> ! 1950: ** R ! 1951: ** N ! 1952: ** I<int> ! 1953: ** F<ieee-float> ! 1954: ** B<size>:<bytes> ! 1955: ** T<size>:<text> ! 1956: ** ! 1957: ** <sql> is the original SQL text for each statement run and <n> is ! 1958: ** the size of that text. The SQL text is UTF-8. A single R character ! 1959: ** occurs before the start of each row. N means a NULL value. ! 1960: ** I mean an 8-byte little-endian integer <int>. F is a floating point ! 1961: ** number with an 8-byte little-endian IEEE floating point value <ieee-float>. ! 1962: ** B means blobs of <size> bytes. T means text rendered as <size> ! 1963: ** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII ! 1964: ** text integers. ! 1965: ** ! 1966: ** For each SQL statement in the X input, there is one S segment. Each ! 1967: ** S segment is followed by zero or more R segments, one for each row in the ! 1968: ** result set. After each R, there are one or more N, I, F, B, or T segments, ! 1969: ** one for each column in the result set. Segments are concatentated directly ! 1970: ** with no delimiters of any kind. ! 1971: */ ! 1972: static void sha3QueryFunc( ! 1973: sqlite3_context *context, ! 1974: int argc, ! 1975: sqlite3_value **argv ! 1976: ){ ! 1977: sqlite3 *db = sqlite3_context_db_handle(context); ! 1978: const char *zSql = (const char*)sqlite3_value_text(argv[0]); ! 1979: sqlite3_stmt *pStmt = 0; ! 1980: int nCol; /* Number of columns in the result set */ ! 1981: int i; /* Loop counter */ ! 1982: int rc; ! 1983: int n; ! 1984: const char *z; ! 1985: SHA3Context cx; ! 1986: int iSize; ! 1987: ! 1988: if( argc==1 ){ ! 1989: iSize = 256; ! 1990: }else{ ! 1991: iSize = sqlite3_value_int(argv[1]); ! 1992: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ ! 1993: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " ! 1994: "384 512", -1); ! 1995: return; ! 1996: } ! 1997: } ! 1998: if( zSql==0 ) return; ! 1999: SHA3Init(&cx, iSize); ! 2000: while( zSql[0] ){ ! 2001: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); ! 2002: if( rc ){ ! 2003: char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", ! 2004: zSql, sqlite3_errmsg(db)); ! 2005: sqlite3_finalize(pStmt); ! 2006: sqlite3_result_error(context, zMsg, -1); ! 2007: sqlite3_free(zMsg); ! 2008: return; ! 2009: } ! 2010: if( !sqlite3_stmt_readonly(pStmt) ){ ! 2011: char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); ! 2012: sqlite3_finalize(pStmt); ! 2013: sqlite3_result_error(context, zMsg, -1); ! 2014: sqlite3_free(zMsg); ! 2015: return; ! 2016: } ! 2017: nCol = sqlite3_column_count(pStmt); ! 2018: z = sqlite3_sql(pStmt); ! 2019: n = (int)strlen(z); ! 2020: hash_step_vformat(&cx,"S%d:",n); ! 2021: SHA3Update(&cx,(unsigned char*)z,n); ! 2022: ! 2023: /* Compute a hash over the result of the query */ ! 2024: while( SQLITE_ROW==sqlite3_step(pStmt) ){ ! 2025: SHA3Update(&cx,(const unsigned char*)"R",1); ! 2026: for(i=0; i<nCol; i++){ ! 2027: switch( sqlite3_column_type(pStmt,i) ){ ! 2028: case SQLITE_NULL: { ! 2029: SHA3Update(&cx, (const unsigned char*)"N",1); ! 2030: break; 1.2 misho 2031: } 1.5 ! misho 2032: case SQLITE_INTEGER: { ! 2033: sqlite3_uint64 u; ! 2034: int j; ! 2035: unsigned char x[9]; ! 2036: sqlite3_int64 v = sqlite3_column_int64(pStmt,i); ! 2037: memcpy(&u, &v, 8); ! 2038: for(j=8; j>=1; j--){ ! 2039: x[j] = u & 0xff; ! 2040: u >>= 8; 1.3 misho 2041: } 1.5 ! misho 2042: x[0] = 'I'; ! 2043: SHA3Update(&cx, x, 9); ! 2044: break; 1.2 misho 2045: } 1.5 ! misho 2046: case SQLITE_FLOAT: { ! 2047: sqlite3_uint64 u; ! 2048: int j; ! 2049: unsigned char x[9]; ! 2050: double r = sqlite3_column_double(pStmt,i); ! 2051: memcpy(&u, &r, 8); ! 2052: for(j=8; j>=1; j--){ ! 2053: x[j] = u & 0xff; ! 2054: u >>= 8; 1.2 misho 2055: } 1.5 ! misho 2056: x[0] = 'F'; ! 2057: SHA3Update(&cx,x,9); ! 2058: break; ! 2059: } ! 2060: case SQLITE_TEXT: { ! 2061: int n2 = sqlite3_column_bytes(pStmt, i); ! 2062: const unsigned char *z2 = sqlite3_column_text(pStmt, i); ! 2063: hash_step_vformat(&cx,"T%d:",n2); ! 2064: SHA3Update(&cx, z2, n2); ! 2065: break; ! 2066: } ! 2067: case SQLITE_BLOB: { ! 2068: int n2 = sqlite3_column_bytes(pStmt, i); ! 2069: const unsigned char *z2 = sqlite3_column_blob(pStmt, i); ! 2070: hash_step_vformat(&cx,"B%d:",n2); ! 2071: SHA3Update(&cx, z2, n2); ! 2072: break; 1.2 misho 2073: } 2074: } 2075: } 1.5 ! misho 2076: } ! 2077: sqlite3_finalize(pStmt); ! 2078: } ! 2079: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); ! 2080: } ! 2081: ! 2082: ! 2083: #ifdef _WIN32 ! 2084: ! 2085: #endif ! 2086: int sqlite3_shathree_init( ! 2087: sqlite3 *db, ! 2088: char **pzErrMsg, ! 2089: const sqlite3_api_routines *pApi ! 2090: ){ ! 2091: int rc = SQLITE_OK; ! 2092: SQLITE_EXTENSION_INIT2(pApi); ! 2093: (void)pzErrMsg; /* Unused parameter */ ! 2094: rc = sqlite3_create_function(db, "sha3", 1, ! 2095: SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, ! 2096: 0, sha3Func, 0, 0); ! 2097: if( rc==SQLITE_OK ){ ! 2098: rc = sqlite3_create_function(db, "sha3", 2, ! 2099: SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, ! 2100: 0, sha3Func, 0, 0); ! 2101: } ! 2102: if( rc==SQLITE_OK ){ ! 2103: rc = sqlite3_create_function(db, "sha3_query", 1, ! 2104: SQLITE_UTF8 | SQLITE_DIRECTONLY, ! 2105: 0, sha3QueryFunc, 0, 0); ! 2106: } ! 2107: if( rc==SQLITE_OK ){ ! 2108: rc = sqlite3_create_function(db, "sha3_query", 2, ! 2109: SQLITE_UTF8 | SQLITE_DIRECTONLY, ! 2110: 0, sha3QueryFunc, 0, 0); ! 2111: } ! 2112: return rc; ! 2113: } ! 2114: ! 2115: /************************* End ../ext/misc/shathree.c ********************/ ! 2116: /************************* Begin ../ext/misc/fileio.c ******************/ ! 2117: /* ! 2118: ** 2014-06-13 ! 2119: ** ! 2120: ** The author disclaims copyright to this source code. In place of ! 2121: ** a legal notice, here is a blessing: ! 2122: ** ! 2123: ** May you do good and not evil. ! 2124: ** May you find forgiveness for yourself and forgive others. ! 2125: ** May you share freely, never taking more than you give. ! 2126: ** ! 2127: ****************************************************************************** ! 2128: ** ! 2129: ** This SQLite extension implements SQL functions readfile() and ! 2130: ** writefile(), and eponymous virtual type "fsdir". ! 2131: ** ! 2132: ** WRITEFILE(FILE, DATA [, MODE [, MTIME]]): ! 2133: ** ! 2134: ** If neither of the optional arguments is present, then this UDF ! 2135: ** function writes blob DATA to file FILE. If successful, the number ! 2136: ** of bytes written is returned. If an error occurs, NULL is returned. ! 2137: ** ! 2138: ** If the first option argument - MODE - is present, then it must ! 2139: ** be passed an integer value that corresponds to a POSIX mode ! 2140: ** value (file type + permissions, as returned in the stat.st_mode ! 2141: ** field by the stat() system call). Three types of files may ! 2142: ** be written/created: ! 2143: ** ! 2144: ** regular files: (mode & 0170000)==0100000 ! 2145: ** symbolic links: (mode & 0170000)==0120000 ! 2146: ** directories: (mode & 0170000)==0040000 ! 2147: ** ! 2148: ** For a directory, the DATA is ignored. For a symbolic link, it is ! 2149: ** interpreted as text and used as the target of the link. For a ! 2150: ** regular file, it is interpreted as a blob and written into the ! 2151: ** named file. Regardless of the type of file, its permissions are ! 2152: ** set to (mode & 0777) before returning. ! 2153: ** ! 2154: ** If the optional MTIME argument is present, then it is interpreted ! 2155: ** as an integer - the number of seconds since the unix epoch. The ! 2156: ** modification-time of the target file is set to this value before ! 2157: ** returning. ! 2158: ** ! 2159: ** If three or more arguments are passed to this function and an ! 2160: ** error is encountered, an exception is raised. ! 2161: ** ! 2162: ** READFILE(FILE): ! 2163: ** ! 2164: ** Read and return the contents of file FILE (type blob) from disk. ! 2165: ** ! 2166: ** FSDIR: ! 2167: ** ! 2168: ** Used as follows: ! 2169: ** ! 2170: ** SELECT * FROM fsdir($path [, $dir]); ! 2171: ** ! 2172: ** Parameter $path is an absolute or relative pathname. If the file that it ! 2173: ** refers to does not exist, it is an error. If the path refers to a regular ! 2174: ** file or symbolic link, it returns a single row. Or, if the path refers ! 2175: ** to a directory, it returns one row for the directory, and one row for each ! 2176: ** file within the hierarchy rooted at $path. ! 2177: ** ! 2178: ** Each row has the following columns: ! 2179: ** ! 2180: ** name: Path to file or directory (text value). ! 2181: ** mode: Value of stat.st_mode for directory entry (an integer). ! 2182: ** mtime: Value of stat.st_mtime for directory entry (an integer). ! 2183: ** data: For a regular file, a blob containing the file data. For a ! 2184: ** symlink, a text value containing the text of the link. For a ! 2185: ** directory, NULL. ! 2186: ** ! 2187: ** If a non-NULL value is specified for the optional $dir parameter and ! 2188: ** $path is a relative path, then $path is interpreted relative to $dir. ! 2189: ** And the paths returned in the "name" column of the table are also ! 2190: ** relative to directory $dir. ! 2191: */ ! 2192: /* #include "sqlite3ext.h" */ ! 2193: SQLITE_EXTENSION_INIT1 ! 2194: #include <stdio.h> ! 2195: #include <string.h> ! 2196: #include <assert.h> ! 2197: ! 2198: #include <sys/types.h> ! 2199: #include <sys/stat.h> ! 2200: #include <fcntl.h> ! 2201: #if !defined(_WIN32) && !defined(WIN32) ! 2202: # include <unistd.h> ! 2203: # include <dirent.h> ! 2204: # include <utime.h> ! 2205: # include <sys/time.h> ! 2206: #else ! 2207: # include "windows.h" ! 2208: # include <io.h> ! 2209: # include <direct.h> ! 2210: /* # include "test_windirent.h" */ ! 2211: # define dirent DIRENT ! 2212: # ifndef chmod ! 2213: # define chmod _chmod ! 2214: # endif ! 2215: # ifndef stat ! 2216: # define stat _stat ! 2217: # endif ! 2218: # define mkdir(path,mode) _mkdir(path) ! 2219: # define lstat(path,buf) stat(path,buf) ! 2220: #endif ! 2221: #include <time.h> ! 2222: #include <errno.h> ! 2223: ! 2224: ! 2225: /* ! 2226: ** Structure of the fsdir() table-valued function ! 2227: */ ! 2228: /* 0 1 2 3 4 5 */ ! 2229: #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" ! 2230: #define FSDIR_COLUMN_NAME 0 /* Name of the file */ ! 2231: #define FSDIR_COLUMN_MODE 1 /* Access mode */ ! 2232: #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ ! 2233: #define FSDIR_COLUMN_DATA 3 /* File content */ ! 2234: #define FSDIR_COLUMN_PATH 4 /* Path to top of search */ ! 2235: #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ ! 2236: ! 2237: ! 2238: /* ! 2239: ** Set the result stored by context ctx to a blob containing the ! 2240: ** contents of file zName. Or, leave the result unchanged (NULL) ! 2241: ** if the file does not exist or is unreadable. ! 2242: ** ! 2243: ** If the file exceeds the SQLite blob size limit, through an ! 2244: ** SQLITE_TOOBIG error. ! 2245: ** ! 2246: ** Throw an SQLITE_IOERR if there are difficulties pulling the file ! 2247: ** off of disk. ! 2248: */ ! 2249: static void readFileContents(sqlite3_context *ctx, const char *zName){ ! 2250: FILE *in; ! 2251: sqlite3_int64 nIn; ! 2252: void *pBuf; ! 2253: sqlite3 *db; ! 2254: int mxBlob; ! 2255: ! 2256: in = fopen(zName, "rb"); ! 2257: if( in==0 ){ ! 2258: /* File does not exist or is unreadable. Leave the result set to NULL. */ ! 2259: return; ! 2260: } ! 2261: fseek(in, 0, SEEK_END); ! 2262: nIn = ftell(in); ! 2263: rewind(in); ! 2264: db = sqlite3_context_db_handle(ctx); ! 2265: mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1); ! 2266: if( nIn>mxBlob ){ ! 2267: sqlite3_result_error_code(ctx, SQLITE_TOOBIG); ! 2268: fclose(in); ! 2269: return; ! 2270: } ! 2271: pBuf = sqlite3_malloc64( nIn ? nIn : 1 ); ! 2272: if( pBuf==0 ){ ! 2273: sqlite3_result_error_nomem(ctx); ! 2274: fclose(in); ! 2275: return; ! 2276: } ! 2277: if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){ ! 2278: sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free); ! 2279: }else{ ! 2280: sqlite3_result_error_code(ctx, SQLITE_IOERR); ! 2281: sqlite3_free(pBuf); ! 2282: } ! 2283: fclose(in); ! 2284: } ! 2285: ! 2286: /* ! 2287: ** Implementation of the "readfile(X)" SQL function. The entire content ! 2288: ** of the file named X is read and returned as a BLOB. NULL is returned ! 2289: ** if the file does not exist or is unreadable. ! 2290: */ ! 2291: static void readfileFunc( ! 2292: sqlite3_context *context, ! 2293: int argc, ! 2294: sqlite3_value **argv ! 2295: ){ ! 2296: const char *zName; ! 2297: (void)(argc); /* Unused parameter */ ! 2298: zName = (const char*)sqlite3_value_text(argv[0]); ! 2299: if( zName==0 ) return; ! 2300: readFileContents(context, zName); ! 2301: } ! 2302: ! 2303: /* ! 2304: ** Set the error message contained in context ctx to the results of ! 2305: ** vprintf(zFmt, ...). ! 2306: */ ! 2307: static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ! 2308: char *zMsg = 0; ! 2309: va_list ap; ! 2310: va_start(ap, zFmt); ! 2311: zMsg = sqlite3_vmprintf(zFmt, ap); ! 2312: sqlite3_result_error(ctx, zMsg, -1); ! 2313: sqlite3_free(zMsg); ! 2314: va_end(ap); ! 2315: } ! 2316: ! 2317: #if defined(_WIN32) ! 2318: /* ! 2319: ** This function is designed to convert a Win32 FILETIME structure into the ! 2320: ** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC). ! 2321: */ ! 2322: static sqlite3_uint64 fileTimeToUnixTime( ! 2323: LPFILETIME pFileTime ! 2324: ){ ! 2325: SYSTEMTIME epochSystemTime; ! 2326: ULARGE_INTEGER epochIntervals; ! 2327: FILETIME epochFileTime; ! 2328: ULARGE_INTEGER fileIntervals; ! 2329: ! 2330: memset(&epochSystemTime, 0, sizeof(SYSTEMTIME)); ! 2331: epochSystemTime.wYear = 1970; ! 2332: epochSystemTime.wMonth = 1; ! 2333: epochSystemTime.wDay = 1; ! 2334: SystemTimeToFileTime(&epochSystemTime, &epochFileTime); ! 2335: epochIntervals.LowPart = epochFileTime.dwLowDateTime; ! 2336: epochIntervals.HighPart = epochFileTime.dwHighDateTime; ! 2337: ! 2338: fileIntervals.LowPart = pFileTime->dwLowDateTime; ! 2339: fileIntervals.HighPart = pFileTime->dwHighDateTime; ! 2340: ! 2341: return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; ! 2342: } ! 2343: ! 2344: /* ! 2345: ** This function attempts to normalize the time values found in the stat() ! 2346: ** buffer to UTC. This is necessary on Win32, where the runtime library ! 2347: ** appears to return these values as local times. ! 2348: */ ! 2349: static void statTimesToUtc( ! 2350: const char *zPath, ! 2351: struct stat *pStatBuf ! 2352: ){ ! 2353: HANDLE hFindFile; ! 2354: WIN32_FIND_DATAW fd; ! 2355: LPWSTR zUnicodeName; ! 2356: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); ! 2357: zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); ! 2358: if( zUnicodeName ){ ! 2359: memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); ! 2360: hFindFile = FindFirstFileW(zUnicodeName, &fd); ! 2361: if( hFindFile!=NULL ){ ! 2362: pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); ! 2363: pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); ! 2364: pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); ! 2365: FindClose(hFindFile); ! 2366: } ! 2367: sqlite3_free(zUnicodeName); ! 2368: } ! 2369: } ! 2370: #endif ! 2371: ! 2372: /* ! 2373: ** This function is used in place of stat(). On Windows, special handling ! 2374: ** is required in order for the included time to be returned as UTC. On all ! 2375: ** other systems, this function simply calls stat(). ! 2376: */ ! 2377: static int fileStat( ! 2378: const char *zPath, ! 2379: struct stat *pStatBuf ! 2380: ){ ! 2381: #if defined(_WIN32) ! 2382: int rc = stat(zPath, pStatBuf); ! 2383: if( rc==0 ) statTimesToUtc(zPath, pStatBuf); ! 2384: return rc; ! 2385: #else ! 2386: return stat(zPath, pStatBuf); ! 2387: #endif ! 2388: } ! 2389: ! 2390: /* ! 2391: ** This function is used in place of lstat(). On Windows, special handling ! 2392: ** is required in order for the included time to be returned as UTC. On all ! 2393: ** other systems, this function simply calls lstat(). ! 2394: */ ! 2395: static int fileLinkStat( ! 2396: const char *zPath, ! 2397: struct stat *pStatBuf ! 2398: ){ ! 2399: #if defined(_WIN32) ! 2400: int rc = lstat(zPath, pStatBuf); ! 2401: if( rc==0 ) statTimesToUtc(zPath, pStatBuf); ! 2402: return rc; ! 2403: #else ! 2404: return lstat(zPath, pStatBuf); ! 2405: #endif ! 2406: } ! 2407: ! 2408: /* ! 2409: ** Argument zFile is the name of a file that will be created and/or written ! 2410: ** by SQL function writefile(). This function ensures that the directory ! 2411: ** zFile will be written to exists, creating it if required. The permissions ! 2412: ** for any path components created by this function are set in accordance ! 2413: ** with the current umask. ! 2414: ** ! 2415: ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise, ! 2416: ** SQLITE_OK is returned if the directory is successfully created, or ! 2417: ** SQLITE_ERROR otherwise. ! 2418: */ ! 2419: static int makeDirectory( ! 2420: const char *zFile ! 2421: ){ ! 2422: char *zCopy = sqlite3_mprintf("%s", zFile); ! 2423: int rc = SQLITE_OK; ! 2424: ! 2425: if( zCopy==0 ){ ! 2426: rc = SQLITE_NOMEM; ! 2427: }else{ ! 2428: int nCopy = (int)strlen(zCopy); ! 2429: int i = 1; ! 2430: ! 2431: while( rc==SQLITE_OK ){ ! 2432: struct stat sStat; ! 2433: int rc2; ! 2434: ! 2435: for(; zCopy[i]!='/' && i<nCopy; i++); ! 2436: if( i==nCopy ) break; ! 2437: zCopy[i] = '\0'; ! 2438: ! 2439: rc2 = fileStat(zCopy, &sStat); ! 2440: if( rc2!=0 ){ ! 2441: if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR; ! 2442: }else{ ! 2443: if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR; ! 2444: } ! 2445: zCopy[i] = '/'; ! 2446: i++; ! 2447: } ! 2448: ! 2449: sqlite3_free(zCopy); ! 2450: } ! 2451: ! 2452: return rc; ! 2453: } ! 2454: ! 2455: /* ! 2456: ** This function does the work for the writefile() UDF. Refer to ! 2457: ** header comments at the top of this file for details. ! 2458: */ ! 2459: static int writeFile( ! 2460: sqlite3_context *pCtx, /* Context to return bytes written in */ ! 2461: const char *zFile, /* File to write */ ! 2462: sqlite3_value *pData, /* Data to write */ ! 2463: mode_t mode, /* MODE parameter passed to writefile() */ ! 2464: sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ ! 2465: ){ ! 2466: #if !defined(_WIN32) && !defined(WIN32) ! 2467: if( S_ISLNK(mode) ){ ! 2468: const char *zTo = (const char*)sqlite3_value_text(pData); ! 2469: if( symlink(zTo, zFile)<0 ) return 1; ! 2470: }else ! 2471: #endif ! 2472: { ! 2473: if( S_ISDIR(mode) ){ ! 2474: if( mkdir(zFile, mode) ){ ! 2475: /* The mkdir() call to create the directory failed. This might not ! 2476: ** be an error though - if there is already a directory at the same ! 2477: ** path and either the permissions already match or can be changed ! 2478: ** to do so using chmod(), it is not an error. */ ! 2479: struct stat sStat; ! 2480: if( errno!=EEXIST ! 2481: || 0!=fileStat(zFile, &sStat) ! 2482: || !S_ISDIR(sStat.st_mode) ! 2483: || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777)) ! 2484: ){ ! 2485: return 1; 1.2 misho 2486: } 1.5 ! misho 2487: } ! 2488: }else{ ! 2489: sqlite3_int64 nWrite = 0; ! 2490: const char *z; ! 2491: int rc = 0; ! 2492: FILE *out = fopen(zFile, "wb"); ! 2493: if( out==0 ) return 1; ! 2494: z = (const char*)sqlite3_value_blob(pData); ! 2495: if( z ){ ! 2496: sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out); ! 2497: nWrite = sqlite3_value_bytes(pData); ! 2498: if( nWrite!=n ){ ! 2499: rc = 1; 1.2 misho 2500: } 1.5 ! misho 2501: } ! 2502: fclose(out); ! 2503: if( rc==0 && mode && chmod(zFile, mode & 0777) ){ ! 2504: rc = 1; ! 2505: } ! 2506: if( rc ) return 2; ! 2507: sqlite3_result_int64(pCtx, nWrite); ! 2508: } ! 2509: } ! 2510: ! 2511: if( mtime>=0 ){ ! 2512: #if defined(_WIN32) ! 2513: #if !SQLITE_OS_WINRT ! 2514: /* Windows */ ! 2515: FILETIME lastAccess; ! 2516: FILETIME lastWrite; ! 2517: SYSTEMTIME currentTime; ! 2518: LONGLONG intervals; ! 2519: HANDLE hFile; ! 2520: LPWSTR zUnicodeName; ! 2521: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); ! 2522: ! 2523: GetSystemTime(¤tTime); ! 2524: SystemTimeToFileTime(¤tTime, &lastAccess); ! 2525: intervals = Int32x32To64(mtime, 10000000) + 116444736000000000; ! 2526: lastWrite.dwLowDateTime = (DWORD)intervals; ! 2527: lastWrite.dwHighDateTime = intervals >> 32; ! 2528: zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile); ! 2529: if( zUnicodeName==0 ){ ! 2530: return 1; ! 2531: } ! 2532: hFile = CreateFileW( ! 2533: zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, ! 2534: FILE_FLAG_BACKUP_SEMANTICS, NULL ! 2535: ); ! 2536: sqlite3_free(zUnicodeName); ! 2537: if( hFile!=INVALID_HANDLE_VALUE ){ ! 2538: BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite); ! 2539: CloseHandle(hFile); ! 2540: return !bResult; ! 2541: }else{ ! 2542: return 1; ! 2543: } ! 2544: #endif ! 2545: #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */ ! 2546: /* Recent unix */ ! 2547: struct timespec times[2]; ! 2548: times[0].tv_nsec = times[1].tv_nsec = 0; ! 2549: times[0].tv_sec = time(0); ! 2550: times[1].tv_sec = mtime; ! 2551: if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ ! 2552: return 1; ! 2553: } ! 2554: #else ! 2555: /* Legacy unix */ ! 2556: struct timeval times[2]; ! 2557: times[0].tv_usec = times[1].tv_usec = 0; ! 2558: times[0].tv_sec = time(0); ! 2559: times[1].tv_sec = mtime; ! 2560: if( utimes(zFile, times) ){ ! 2561: return 1; ! 2562: } ! 2563: #endif ! 2564: } ! 2565: ! 2566: return 0; ! 2567: } ! 2568: ! 2569: /* ! 2570: ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. ! 2571: ** Refer to header comments at the top of this file for details. ! 2572: */ ! 2573: static void writefileFunc( ! 2574: sqlite3_context *context, ! 2575: int argc, ! 2576: sqlite3_value **argv ! 2577: ){ ! 2578: const char *zFile; ! 2579: mode_t mode = 0; ! 2580: int res; ! 2581: sqlite3_int64 mtime = -1; ! 2582: ! 2583: if( argc<2 || argc>4 ){ ! 2584: sqlite3_result_error(context, ! 2585: "wrong number of arguments to function writefile()", -1 ! 2586: ); ! 2587: return; ! 2588: } ! 2589: ! 2590: zFile = (const char*)sqlite3_value_text(argv[0]); ! 2591: if( zFile==0 ) return; ! 2592: if( argc>=3 ){ ! 2593: mode = (mode_t)sqlite3_value_int(argv[2]); ! 2594: } ! 2595: if( argc==4 ){ ! 2596: mtime = sqlite3_value_int64(argv[3]); ! 2597: } ! 2598: ! 2599: res = writeFile(context, zFile, argv[1], mode, mtime); ! 2600: if( res==1 && errno==ENOENT ){ ! 2601: if( makeDirectory(zFile)==SQLITE_OK ){ ! 2602: res = writeFile(context, zFile, argv[1], mode, mtime); ! 2603: } ! 2604: } ! 2605: ! 2606: if( argc>2 && res!=0 ){ ! 2607: if( S_ISLNK(mode) ){ ! 2608: ctxErrorMsg(context, "failed to create symlink: %s", zFile); ! 2609: }else if( S_ISDIR(mode) ){ ! 2610: ctxErrorMsg(context, "failed to create directory: %s", zFile); ! 2611: }else{ ! 2612: ctxErrorMsg(context, "failed to write file: %s", zFile); ! 2613: } ! 2614: } ! 2615: } ! 2616: ! 2617: /* ! 2618: ** SQL function: lsmode(MODE) ! 2619: ** ! 2620: ** Given a numberic st_mode from stat(), convert it into a human-readable ! 2621: ** text string in the style of "ls -l". ! 2622: */ ! 2623: static void lsModeFunc( ! 2624: sqlite3_context *context, ! 2625: int argc, ! 2626: sqlite3_value **argv ! 2627: ){ ! 2628: int i; ! 2629: int iMode = sqlite3_value_int(argv[0]); ! 2630: char z[16]; ! 2631: (void)argc; ! 2632: if( S_ISLNK(iMode) ){ ! 2633: z[0] = 'l'; ! 2634: }else if( S_ISREG(iMode) ){ ! 2635: z[0] = '-'; ! 2636: }else if( S_ISDIR(iMode) ){ ! 2637: z[0] = 'd'; ! 2638: }else{ ! 2639: z[0] = '?'; ! 2640: } ! 2641: for(i=0; i<3; i++){ ! 2642: int m = (iMode >> ((2-i)*3)); ! 2643: char *a = &z[1 + i*3]; ! 2644: a[0] = (m & 0x4) ? 'r' : '-'; ! 2645: a[1] = (m & 0x2) ? 'w' : '-'; ! 2646: a[2] = (m & 0x1) ? 'x' : '-'; ! 2647: } ! 2648: z[10] = '\0'; ! 2649: sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); ! 2650: } ! 2651: ! 2652: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 2653: ! 2654: /* ! 2655: ** Cursor type for recursively iterating through a directory structure. ! 2656: */ ! 2657: typedef struct fsdir_cursor fsdir_cursor; ! 2658: typedef struct FsdirLevel FsdirLevel; ! 2659: ! 2660: struct FsdirLevel { ! 2661: DIR *pDir; /* From opendir() */ ! 2662: char *zDir; /* Name of directory (nul-terminated) */ ! 2663: }; ! 2664: ! 2665: struct fsdir_cursor { ! 2666: sqlite3_vtab_cursor base; /* Base class - must be first */ ! 2667: ! 2668: int nLvl; /* Number of entries in aLvl[] array */ ! 2669: int iLvl; /* Index of current entry */ ! 2670: FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ ! 2671: ! 2672: const char *zBase; ! 2673: int nBase; ! 2674: ! 2675: struct stat sStat; /* Current lstat() results */ ! 2676: char *zPath; /* Path to current entry */ ! 2677: sqlite3_int64 iRowid; /* Current rowid */ ! 2678: }; ! 2679: ! 2680: typedef struct fsdir_tab fsdir_tab; ! 2681: struct fsdir_tab { ! 2682: sqlite3_vtab base; /* Base class - must be first */ ! 2683: }; ! 2684: ! 2685: /* ! 2686: ** Construct a new fsdir virtual table object. ! 2687: */ ! 2688: static int fsdirConnect( ! 2689: sqlite3 *db, ! 2690: void *pAux, ! 2691: int argc, const char *const*argv, ! 2692: sqlite3_vtab **ppVtab, ! 2693: char **pzErr ! 2694: ){ ! 2695: fsdir_tab *pNew = 0; ! 2696: int rc; ! 2697: (void)pAux; ! 2698: (void)argc; ! 2699: (void)argv; ! 2700: (void)pzErr; ! 2701: rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); ! 2702: if( rc==SQLITE_OK ){ ! 2703: pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); ! 2704: if( pNew==0 ) return SQLITE_NOMEM; ! 2705: memset(pNew, 0, sizeof(*pNew)); ! 2706: sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); ! 2707: } ! 2708: *ppVtab = (sqlite3_vtab*)pNew; ! 2709: return rc; ! 2710: } ! 2711: ! 2712: /* ! 2713: ** This method is the destructor for fsdir vtab objects. ! 2714: */ ! 2715: static int fsdirDisconnect(sqlite3_vtab *pVtab){ ! 2716: sqlite3_free(pVtab); ! 2717: return SQLITE_OK; ! 2718: } ! 2719: ! 2720: /* ! 2721: ** Constructor for a new fsdir_cursor object. ! 2722: */ ! 2723: static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ! 2724: fsdir_cursor *pCur; ! 2725: (void)p; ! 2726: pCur = sqlite3_malloc( sizeof(*pCur) ); ! 2727: if( pCur==0 ) return SQLITE_NOMEM; ! 2728: memset(pCur, 0, sizeof(*pCur)); ! 2729: pCur->iLvl = -1; ! 2730: *ppCursor = &pCur->base; ! 2731: return SQLITE_OK; ! 2732: } ! 2733: ! 2734: /* ! 2735: ** Reset a cursor back to the state it was in when first returned ! 2736: ** by fsdirOpen(). ! 2737: */ ! 2738: static void fsdirResetCursor(fsdir_cursor *pCur){ ! 2739: int i; ! 2740: for(i=0; i<=pCur->iLvl; i++){ ! 2741: FsdirLevel *pLvl = &pCur->aLvl[i]; ! 2742: if( pLvl->pDir ) closedir(pLvl->pDir); ! 2743: sqlite3_free(pLvl->zDir); ! 2744: } ! 2745: sqlite3_free(pCur->zPath); ! 2746: sqlite3_free(pCur->aLvl); ! 2747: pCur->aLvl = 0; ! 2748: pCur->zPath = 0; ! 2749: pCur->zBase = 0; ! 2750: pCur->nBase = 0; ! 2751: pCur->nLvl = 0; ! 2752: pCur->iLvl = -1; ! 2753: pCur->iRowid = 1; ! 2754: } ! 2755: ! 2756: /* ! 2757: ** Destructor for an fsdir_cursor. ! 2758: */ ! 2759: static int fsdirClose(sqlite3_vtab_cursor *cur){ ! 2760: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2761: ! 2762: fsdirResetCursor(pCur); ! 2763: sqlite3_free(pCur); ! 2764: return SQLITE_OK; ! 2765: } ! 2766: ! 2767: /* ! 2768: ** Set the error message for the virtual table associated with cursor ! 2769: ** pCur to the results of vprintf(zFmt, ...). ! 2770: */ ! 2771: static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){ ! 2772: va_list ap; ! 2773: va_start(ap, zFmt); ! 2774: pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); ! 2775: va_end(ap); ! 2776: } ! 2777: ! 2778: ! 2779: /* ! 2780: ** Advance an fsdir_cursor to its next row of output. ! 2781: */ ! 2782: static int fsdirNext(sqlite3_vtab_cursor *cur){ ! 2783: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2784: mode_t m = pCur->sStat.st_mode; ! 2785: ! 2786: pCur->iRowid++; ! 2787: if( S_ISDIR(m) ){ ! 2788: /* Descend into this directory */ ! 2789: int iNew = pCur->iLvl + 1; ! 2790: FsdirLevel *pLvl; ! 2791: if( iNew>=pCur->nLvl ){ ! 2792: int nNew = iNew+1; ! 2793: sqlite3_int64 nByte = nNew*sizeof(FsdirLevel); ! 2794: FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte); ! 2795: if( aNew==0 ) return SQLITE_NOMEM; ! 2796: memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl)); ! 2797: pCur->aLvl = aNew; ! 2798: pCur->nLvl = nNew; ! 2799: } ! 2800: pCur->iLvl = iNew; ! 2801: pLvl = &pCur->aLvl[iNew]; ! 2802: ! 2803: pLvl->zDir = pCur->zPath; ! 2804: pCur->zPath = 0; ! 2805: pLvl->pDir = opendir(pLvl->zDir); ! 2806: if( pLvl->pDir==0 ){ ! 2807: fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); ! 2808: return SQLITE_ERROR; ! 2809: } ! 2810: } ! 2811: ! 2812: while( pCur->iLvl>=0 ){ ! 2813: FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl]; ! 2814: struct dirent *pEntry = readdir(pLvl->pDir); ! 2815: if( pEntry ){ ! 2816: if( pEntry->d_name[0]=='.' ){ ! 2817: if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue; ! 2818: if( pEntry->d_name[1]=='\0' ) continue; ! 2819: } ! 2820: sqlite3_free(pCur->zPath); ! 2821: pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name); ! 2822: if( pCur->zPath==0 ) return SQLITE_NOMEM; ! 2823: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ ! 2824: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); ! 2825: return SQLITE_ERROR; ! 2826: } ! 2827: return SQLITE_OK; ! 2828: } ! 2829: closedir(pLvl->pDir); ! 2830: sqlite3_free(pLvl->zDir); ! 2831: pLvl->pDir = 0; ! 2832: pLvl->zDir = 0; ! 2833: pCur->iLvl--; ! 2834: } ! 2835: ! 2836: /* EOF */ ! 2837: sqlite3_free(pCur->zPath); ! 2838: pCur->zPath = 0; ! 2839: return SQLITE_OK; ! 2840: } ! 2841: ! 2842: /* ! 2843: ** Return values of columns for the row at which the series_cursor ! 2844: ** is currently pointing. ! 2845: */ ! 2846: static int fsdirColumn( ! 2847: sqlite3_vtab_cursor *cur, /* The cursor */ ! 2848: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ! 2849: int i /* Which column to return */ ! 2850: ){ ! 2851: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2852: switch( i ){ ! 2853: case FSDIR_COLUMN_NAME: { ! 2854: sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); ! 2855: break; ! 2856: } ! 2857: ! 2858: case FSDIR_COLUMN_MODE: ! 2859: sqlite3_result_int64(ctx, pCur->sStat.st_mode); ! 2860: break; ! 2861: ! 2862: case FSDIR_COLUMN_MTIME: ! 2863: sqlite3_result_int64(ctx, pCur->sStat.st_mtime); ! 2864: break; ! 2865: ! 2866: case FSDIR_COLUMN_DATA: { ! 2867: mode_t m = pCur->sStat.st_mode; ! 2868: if( S_ISDIR(m) ){ ! 2869: sqlite3_result_null(ctx); ! 2870: #if !defined(_WIN32) && !defined(WIN32) ! 2871: }else if( S_ISLNK(m) ){ ! 2872: char aStatic[64]; ! 2873: char *aBuf = aStatic; ! 2874: sqlite3_int64 nBuf = 64; ! 2875: int n; ! 2876: ! 2877: while( 1 ){ ! 2878: n = readlink(pCur->zPath, aBuf, nBuf); ! 2879: if( n<nBuf ) break; ! 2880: if( aBuf!=aStatic ) sqlite3_free(aBuf); ! 2881: nBuf = nBuf*2; ! 2882: aBuf = sqlite3_malloc64(nBuf); ! 2883: if( aBuf==0 ){ ! 2884: sqlite3_result_error_nomem(ctx); ! 2885: return SQLITE_NOMEM; ! 2886: } ! 2887: } ! 2888: ! 2889: sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); ! 2890: if( aBuf!=aStatic ) sqlite3_free(aBuf); ! 2891: #endif ! 2892: }else{ ! 2893: readFileContents(ctx, pCur->zPath); ! 2894: } ! 2895: } ! 2896: case FSDIR_COLUMN_PATH: ! 2897: default: { ! 2898: /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ! 2899: ** always return their values as NULL */ ! 2900: break; ! 2901: } ! 2902: } ! 2903: return SQLITE_OK; ! 2904: } ! 2905: ! 2906: /* ! 2907: ** Return the rowid for the current row. In this implementation, the ! 2908: ** first row returned is assigned rowid value 1, and each subsequent ! 2909: ** row a value 1 more than that of the previous. ! 2910: */ ! 2911: static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ! 2912: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2913: *pRowid = pCur->iRowid; ! 2914: return SQLITE_OK; ! 2915: } ! 2916: ! 2917: /* ! 2918: ** Return TRUE if the cursor has been moved off of the last ! 2919: ** row of output. ! 2920: */ ! 2921: static int fsdirEof(sqlite3_vtab_cursor *cur){ ! 2922: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2923: return (pCur->zPath==0); ! 2924: } ! 2925: ! 2926: /* ! 2927: ** xFilter callback. ! 2928: ** ! 2929: ** idxNum==1 PATH parameter only ! 2930: ** idxNum==2 Both PATH and DIR supplied ! 2931: */ ! 2932: static int fsdirFilter( ! 2933: sqlite3_vtab_cursor *cur, ! 2934: int idxNum, const char *idxStr, ! 2935: int argc, sqlite3_value **argv ! 2936: ){ ! 2937: const char *zDir = 0; ! 2938: fsdir_cursor *pCur = (fsdir_cursor*)cur; ! 2939: (void)idxStr; ! 2940: fsdirResetCursor(pCur); ! 2941: ! 2942: if( idxNum==0 ){ ! 2943: fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); ! 2944: return SQLITE_ERROR; ! 2945: } ! 2946: ! 2947: assert( argc==idxNum && (argc==1 || argc==2) ); ! 2948: zDir = (const char*)sqlite3_value_text(argv[0]); ! 2949: if( zDir==0 ){ ! 2950: fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument"); ! 2951: return SQLITE_ERROR; ! 2952: } ! 2953: if( argc==2 ){ ! 2954: pCur->zBase = (const char*)sqlite3_value_text(argv[1]); ! 2955: } ! 2956: if( pCur->zBase ){ ! 2957: pCur->nBase = (int)strlen(pCur->zBase)+1; ! 2958: pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir); ! 2959: }else{ ! 2960: pCur->zPath = sqlite3_mprintf("%s", zDir); ! 2961: } ! 2962: ! 2963: if( pCur->zPath==0 ){ ! 2964: return SQLITE_NOMEM; ! 2965: } ! 2966: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ ! 2967: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); ! 2968: return SQLITE_ERROR; ! 2969: } ! 2970: ! 2971: return SQLITE_OK; ! 2972: } ! 2973: ! 2974: /* ! 2975: ** SQLite will invoke this method one or more times while planning a query ! 2976: ** that uses the generate_series virtual table. This routine needs to create ! 2977: ** a query plan for each invocation and compute an estimated cost for that ! 2978: ** plan. ! 2979: ** ! 2980: ** In this implementation idxNum is used to represent the ! 2981: ** query plan. idxStr is unused. ! 2982: ** ! 2983: ** The query plan is represented by values of idxNum: ! 2984: ** ! 2985: ** (1) The path value is supplied by argv[0] ! 2986: ** (2) Path is in argv[0] and dir is in argv[1] ! 2987: */ ! 2988: static int fsdirBestIndex( ! 2989: sqlite3_vtab *tab, ! 2990: sqlite3_index_info *pIdxInfo ! 2991: ){ ! 2992: int i; /* Loop over constraints */ ! 2993: int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ ! 2994: int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ ! 2995: int seenPath = 0; /* True if an unusable PATH= constraint is seen */ ! 2996: int seenDir = 0; /* True if an unusable DIR= constraint is seen */ ! 2997: const struct sqlite3_index_constraint *pConstraint; ! 2998: ! 2999: (void)tab; ! 3000: pConstraint = pIdxInfo->aConstraint; ! 3001: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ ! 3002: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; ! 3003: switch( pConstraint->iColumn ){ ! 3004: case FSDIR_COLUMN_PATH: { ! 3005: if( pConstraint->usable ){ ! 3006: idxPath = i; ! 3007: seenPath = 0; ! 3008: }else if( idxPath<0 ){ ! 3009: seenPath = 1; ! 3010: } ! 3011: break; ! 3012: } ! 3013: case FSDIR_COLUMN_DIR: { ! 3014: if( pConstraint->usable ){ ! 3015: idxDir = i; ! 3016: seenDir = 0; ! 3017: }else if( idxDir<0 ){ ! 3018: seenDir = 1; ! 3019: } ! 3020: break; ! 3021: } ! 3022: } ! 3023: } ! 3024: if( seenPath || seenDir ){ ! 3025: /* If input parameters are unusable, disallow this plan */ ! 3026: return SQLITE_CONSTRAINT; ! 3027: } ! 3028: ! 3029: if( idxPath<0 ){ ! 3030: pIdxInfo->idxNum = 0; ! 3031: /* The pIdxInfo->estimatedCost should have been initialized to a huge ! 3032: ** number. Leave it unchanged. */ ! 3033: pIdxInfo->estimatedRows = 0x7fffffff; ! 3034: }else{ ! 3035: pIdxInfo->aConstraintUsage[idxPath].omit = 1; ! 3036: pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; ! 3037: if( idxDir>=0 ){ ! 3038: pIdxInfo->aConstraintUsage[idxDir].omit = 1; ! 3039: pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; ! 3040: pIdxInfo->idxNum = 2; ! 3041: pIdxInfo->estimatedCost = 10.0; ! 3042: }else{ ! 3043: pIdxInfo->idxNum = 1; ! 3044: pIdxInfo->estimatedCost = 100.0; ! 3045: } ! 3046: } ! 3047: ! 3048: return SQLITE_OK; ! 3049: } ! 3050: ! 3051: /* ! 3052: ** Register the "fsdir" virtual table. ! 3053: */ ! 3054: static int fsdirRegister(sqlite3 *db){ ! 3055: static sqlite3_module fsdirModule = { ! 3056: 0, /* iVersion */ ! 3057: 0, /* xCreate */ ! 3058: fsdirConnect, /* xConnect */ ! 3059: fsdirBestIndex, /* xBestIndex */ ! 3060: fsdirDisconnect, /* xDisconnect */ ! 3061: 0, /* xDestroy */ ! 3062: fsdirOpen, /* xOpen - open a cursor */ ! 3063: fsdirClose, /* xClose - close a cursor */ ! 3064: fsdirFilter, /* xFilter - configure scan constraints */ ! 3065: fsdirNext, /* xNext - advance a cursor */ ! 3066: fsdirEof, /* xEof - check for end of scan */ ! 3067: fsdirColumn, /* xColumn - read data */ ! 3068: fsdirRowid, /* xRowid - read data */ ! 3069: 0, /* xUpdate */ ! 3070: 0, /* xBegin */ ! 3071: 0, /* xSync */ ! 3072: 0, /* xCommit */ ! 3073: 0, /* xRollback */ ! 3074: 0, /* xFindMethod */ ! 3075: 0, /* xRename */ ! 3076: 0, /* xSavepoint */ ! 3077: 0, /* xRelease */ ! 3078: 0, /* xRollbackTo */ ! 3079: 0, /* xShadowName */ ! 3080: }; ! 3081: ! 3082: int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); ! 3083: return rc; ! 3084: } ! 3085: #else /* SQLITE_OMIT_VIRTUALTABLE */ ! 3086: # define fsdirRegister(x) SQLITE_OK ! 3087: #endif ! 3088: ! 3089: #ifdef _WIN32 ! 3090: ! 3091: #endif ! 3092: int sqlite3_fileio_init( ! 3093: sqlite3 *db, ! 3094: char **pzErrMsg, ! 3095: const sqlite3_api_routines *pApi ! 3096: ){ ! 3097: int rc = SQLITE_OK; ! 3098: SQLITE_EXTENSION_INIT2(pApi); ! 3099: (void)pzErrMsg; /* Unused parameter */ ! 3100: rc = sqlite3_create_function(db, "readfile", 1, ! 3101: SQLITE_UTF8|SQLITE_DIRECTONLY, 0, ! 3102: readfileFunc, 0, 0); ! 3103: if( rc==SQLITE_OK ){ ! 3104: rc = sqlite3_create_function(db, "writefile", -1, ! 3105: SQLITE_UTF8|SQLITE_DIRECTONLY, 0, ! 3106: writefileFunc, 0, 0); ! 3107: } ! 3108: if( rc==SQLITE_OK ){ ! 3109: rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, ! 3110: lsModeFunc, 0, 0); ! 3111: } ! 3112: if( rc==SQLITE_OK ){ ! 3113: rc = fsdirRegister(db); ! 3114: } ! 3115: return rc; ! 3116: } ! 3117: ! 3118: /************************* End ../ext/misc/fileio.c ********************/ ! 3119: /************************* Begin ../ext/misc/completion.c ******************/ ! 3120: /* ! 3121: ** 2017-07-10 ! 3122: ** ! 3123: ** The author disclaims copyright to this source code. In place of ! 3124: ** a legal notice, here is a blessing: ! 3125: ** ! 3126: ** May you do good and not evil. ! 3127: ** May you find forgiveness for yourself and forgive others. ! 3128: ** May you share freely, never taking more than you give. ! 3129: ** ! 3130: ************************************************************************* ! 3131: ** ! 3132: ** This file implements an eponymous virtual table that returns suggested ! 3133: ** completions for a partial SQL input. ! 3134: ** ! 3135: ** Suggested usage: ! 3136: ** ! 3137: ** SELECT DISTINCT candidate COLLATE nocase ! 3138: ** FROM completion($prefix,$wholeline) ! 3139: ** ORDER BY 1; ! 3140: ** ! 3141: ** The two query parameters are optional. $prefix is the text of the ! 3142: ** current word being typed and that is to be completed. $wholeline is ! 3143: ** the complete input line, used for context. ! 3144: ** ! 3145: ** The raw completion() table might return the same candidate multiple ! 3146: ** times, for example if the same column name is used to two or more ! 3147: ** tables. And the candidates are returned in an arbitrary order. Hence, ! 3148: ** the DISTINCT and ORDER BY are recommended. ! 3149: ** ! 3150: ** This virtual table operates at the speed of human typing, and so there ! 3151: ** is no attempt to make it fast. Even a slow implementation will be much ! 3152: ** faster than any human can type. ! 3153: ** ! 3154: */ ! 3155: /* #include "sqlite3ext.h" */ ! 3156: SQLITE_EXTENSION_INIT1 ! 3157: #include <assert.h> ! 3158: #include <string.h> ! 3159: #include <ctype.h> ! 3160: ! 3161: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 3162: ! 3163: /* completion_vtab is a subclass of sqlite3_vtab which will ! 3164: ** serve as the underlying representation of a completion virtual table ! 3165: */ ! 3166: typedef struct completion_vtab completion_vtab; ! 3167: struct completion_vtab { ! 3168: sqlite3_vtab base; /* Base class - must be first */ ! 3169: sqlite3 *db; /* Database connection for this completion vtab */ ! 3170: }; ! 3171: ! 3172: /* completion_cursor is a subclass of sqlite3_vtab_cursor which will ! 3173: ** serve as the underlying representation of a cursor that scans ! 3174: ** over rows of the result ! 3175: */ ! 3176: typedef struct completion_cursor completion_cursor; ! 3177: struct completion_cursor { ! 3178: sqlite3_vtab_cursor base; /* Base class - must be first */ ! 3179: sqlite3 *db; /* Database connection for this cursor */ ! 3180: int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */ ! 3181: char *zPrefix; /* The prefix for the word we want to complete */ ! 3182: char *zLine; /* The whole that we want to complete */ ! 3183: const char *zCurrentRow; /* Current output row */ ! 3184: int szRow; /* Length of the zCurrentRow string */ ! 3185: sqlite3_stmt *pStmt; /* Current statement */ ! 3186: sqlite3_int64 iRowid; /* The rowid */ ! 3187: int ePhase; /* Current phase */ ! 3188: int j; /* inter-phase counter */ ! 3189: }; ! 3190: ! 3191: /* Values for ePhase: ! 3192: */ ! 3193: #define COMPLETION_FIRST_PHASE 1 ! 3194: #define COMPLETION_KEYWORDS 1 ! 3195: #define COMPLETION_PRAGMAS 2 ! 3196: #define COMPLETION_FUNCTIONS 3 ! 3197: #define COMPLETION_COLLATIONS 4 ! 3198: #define COMPLETION_INDEXES 5 ! 3199: #define COMPLETION_TRIGGERS 6 ! 3200: #define COMPLETION_DATABASES 7 ! 3201: #define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */ ! 3202: #define COMPLETION_COLUMNS 9 ! 3203: #define COMPLETION_MODULES 10 ! 3204: #define COMPLETION_EOF 11 ! 3205: ! 3206: /* ! 3207: ** The completionConnect() method is invoked to create a new ! 3208: ** completion_vtab that describes the completion virtual table. ! 3209: ** ! 3210: ** Think of this routine as the constructor for completion_vtab objects. ! 3211: ** ! 3212: ** All this routine needs to do is: ! 3213: ** ! 3214: ** (1) Allocate the completion_vtab object and initialize all fields. ! 3215: ** ! 3216: ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the ! 3217: ** result set of queries against completion will look like. ! 3218: */ ! 3219: static int completionConnect( ! 3220: sqlite3 *db, ! 3221: void *pAux, ! 3222: int argc, const char *const*argv, ! 3223: sqlite3_vtab **ppVtab, ! 3224: char **pzErr ! 3225: ){ ! 3226: completion_vtab *pNew; ! 3227: int rc; ! 3228: ! 3229: (void)(pAux); /* Unused parameter */ ! 3230: (void)(argc); /* Unused parameter */ ! 3231: (void)(argv); /* Unused parameter */ ! 3232: (void)(pzErr); /* Unused parameter */ ! 3233: ! 3234: /* Column numbers */ ! 3235: #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */ ! 3236: #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */ ! 3237: #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */ ! 3238: #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */ ! 3239: ! 3240: sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); ! 3241: rc = sqlite3_declare_vtab(db, ! 3242: "CREATE TABLE x(" ! 3243: " candidate TEXT," ! 3244: " prefix TEXT HIDDEN," ! 3245: " wholeline TEXT HIDDEN," ! 3246: " phase INT HIDDEN" /* Used for debugging only */ ! 3247: ")"); ! 3248: if( rc==SQLITE_OK ){ ! 3249: pNew = sqlite3_malloc( sizeof(*pNew) ); ! 3250: *ppVtab = (sqlite3_vtab*)pNew; ! 3251: if( pNew==0 ) return SQLITE_NOMEM; ! 3252: memset(pNew, 0, sizeof(*pNew)); ! 3253: pNew->db = db; ! 3254: } ! 3255: return rc; ! 3256: } ! 3257: ! 3258: /* ! 3259: ** This method is the destructor for completion_cursor objects. ! 3260: */ ! 3261: static int completionDisconnect(sqlite3_vtab *pVtab){ ! 3262: sqlite3_free(pVtab); ! 3263: return SQLITE_OK; ! 3264: } ! 3265: ! 3266: /* ! 3267: ** Constructor for a new completion_cursor object. ! 3268: */ ! 3269: static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ! 3270: completion_cursor *pCur; ! 3271: pCur = sqlite3_malloc( sizeof(*pCur) ); ! 3272: if( pCur==0 ) return SQLITE_NOMEM; ! 3273: memset(pCur, 0, sizeof(*pCur)); ! 3274: pCur->db = ((completion_vtab*)p)->db; ! 3275: *ppCursor = &pCur->base; ! 3276: return SQLITE_OK; ! 3277: } ! 3278: ! 3279: /* ! 3280: ** Reset the completion_cursor. ! 3281: */ ! 3282: static void completionCursorReset(completion_cursor *pCur){ ! 3283: sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0; ! 3284: sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0; ! 3285: sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0; ! 3286: pCur->j = 0; ! 3287: } ! 3288: ! 3289: /* ! 3290: ** Destructor for a completion_cursor. ! 3291: */ ! 3292: static int completionClose(sqlite3_vtab_cursor *cur){ ! 3293: completionCursorReset((completion_cursor*)cur); ! 3294: sqlite3_free(cur); ! 3295: return SQLITE_OK; ! 3296: } ! 3297: ! 3298: /* ! 3299: ** Advance a completion_cursor to its next row of output. ! 3300: ** ! 3301: ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object ! 3302: ** record the current state of the scan. This routine sets ->zCurrentRow ! 3303: ** to the current row of output and then returns. If no more rows remain, ! 3304: ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual ! 3305: ** table that has reached the end of its scan. ! 3306: ** ! 3307: ** The current implementation just lists potential identifiers and ! 3308: ** keywords and filters them by zPrefix. Future enhancements should ! 3309: ** take zLine into account to try to restrict the set of identifiers and ! 3310: ** keywords based on what would be legal at the current point of input. ! 3311: */ ! 3312: static int completionNext(sqlite3_vtab_cursor *cur){ ! 3313: completion_cursor *pCur = (completion_cursor*)cur; ! 3314: int eNextPhase = 0; /* Next phase to try if current phase reaches end */ ! 3315: int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */ ! 3316: pCur->iRowid++; ! 3317: while( pCur->ePhase!=COMPLETION_EOF ){ ! 3318: switch( pCur->ePhase ){ ! 3319: case COMPLETION_KEYWORDS: { ! 3320: if( pCur->j >= sqlite3_keyword_count() ){ ! 3321: pCur->zCurrentRow = 0; ! 3322: pCur->ePhase = COMPLETION_DATABASES; ! 3323: }else{ ! 3324: sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); ! 3325: } ! 3326: iCol = -1; ! 3327: break; ! 3328: } ! 3329: case COMPLETION_DATABASES: { ! 3330: if( pCur->pStmt==0 ){ ! 3331: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, ! 3332: &pCur->pStmt, 0); ! 3333: } ! 3334: iCol = 1; ! 3335: eNextPhase = COMPLETION_TABLES; ! 3336: break; ! 3337: } ! 3338: case COMPLETION_TABLES: { ! 3339: if( pCur->pStmt==0 ){ ! 3340: sqlite3_stmt *pS2; ! 3341: char *zSql = 0; ! 3342: const char *zSep = ""; ! 3343: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); ! 3344: while( sqlite3_step(pS2)==SQLITE_ROW ){ ! 3345: const char *zDb = (const char*)sqlite3_column_text(pS2, 1); ! 3346: zSql = sqlite3_mprintf( ! 3347: "%z%s" ! 3348: "SELECT name FROM \"%w\".sqlite_schema", ! 3349: zSql, zSep, zDb ! 3350: ); ! 3351: if( zSql==0 ) return SQLITE_NOMEM; ! 3352: zSep = " UNION "; ! 3353: } ! 3354: sqlite3_finalize(pS2); ! 3355: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); ! 3356: sqlite3_free(zSql); ! 3357: } ! 3358: iCol = 0; ! 3359: eNextPhase = COMPLETION_COLUMNS; ! 3360: break; ! 3361: } ! 3362: case COMPLETION_COLUMNS: { ! 3363: if( pCur->pStmt==0 ){ ! 3364: sqlite3_stmt *pS2; ! 3365: char *zSql = 0; ! 3366: const char *zSep = ""; ! 3367: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); ! 3368: while( sqlite3_step(pS2)==SQLITE_ROW ){ ! 3369: const char *zDb = (const char*)sqlite3_column_text(pS2, 1); ! 3370: zSql = sqlite3_mprintf( ! 3371: "%z%s" ! 3372: "SELECT pti.name FROM \"%w\".sqlite_schema AS sm" ! 3373: " JOIN pragma_table_info(sm.name,%Q) AS pti" ! 3374: " WHERE sm.type='table'", ! 3375: zSql, zSep, zDb, zDb ! 3376: ); ! 3377: if( zSql==0 ) return SQLITE_NOMEM; ! 3378: zSep = " UNION "; 1.4 misho 3379: } 1.5 ! misho 3380: sqlite3_finalize(pS2); ! 3381: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); ! 3382: sqlite3_free(zSql); ! 3383: } ! 3384: iCol = 0; ! 3385: eNextPhase = COMPLETION_EOF; ! 3386: break; ! 3387: } ! 3388: } ! 3389: if( iCol<0 ){ ! 3390: /* This case is when the phase presets zCurrentRow */ ! 3391: if( pCur->zCurrentRow==0 ) continue; ! 3392: }else{ ! 3393: if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ ! 3394: /* Extract the next row of content */ ! 3395: pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); ! 3396: pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); ! 3397: }else{ ! 3398: /* When all rows are finished, advance to the next phase */ ! 3399: sqlite3_finalize(pCur->pStmt); ! 3400: pCur->pStmt = 0; ! 3401: pCur->ePhase = eNextPhase; ! 3402: continue; ! 3403: } ! 3404: } ! 3405: if( pCur->nPrefix==0 ) break; ! 3406: if( pCur->nPrefix<=pCur->szRow ! 3407: && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ! 3408: ){ ! 3409: break; ! 3410: } ! 3411: } ! 3412: ! 3413: return SQLITE_OK; ! 3414: } ! 3415: ! 3416: /* ! 3417: ** Return values of columns for the row at which the completion_cursor ! 3418: ** is currently pointing. ! 3419: */ ! 3420: static int completionColumn( ! 3421: sqlite3_vtab_cursor *cur, /* The cursor */ ! 3422: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ! 3423: int i /* Which column to return */ ! 3424: ){ ! 3425: completion_cursor *pCur = (completion_cursor*)cur; ! 3426: switch( i ){ ! 3427: case COMPLETION_COLUMN_CANDIDATE: { ! 3428: sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); ! 3429: break; ! 3430: } ! 3431: case COMPLETION_COLUMN_PREFIX: { ! 3432: sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT); ! 3433: break; ! 3434: } ! 3435: case COMPLETION_COLUMN_WHOLELINE: { ! 3436: sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT); ! 3437: break; ! 3438: } ! 3439: case COMPLETION_COLUMN_PHASE: { ! 3440: sqlite3_result_int(ctx, pCur->ePhase); ! 3441: break; ! 3442: } ! 3443: } ! 3444: return SQLITE_OK; ! 3445: } ! 3446: ! 3447: /* ! 3448: ** Return the rowid for the current row. In this implementation, the ! 3449: ** rowid is the same as the output value. ! 3450: */ ! 3451: static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ! 3452: completion_cursor *pCur = (completion_cursor*)cur; ! 3453: *pRowid = pCur->iRowid; ! 3454: return SQLITE_OK; ! 3455: } ! 3456: ! 3457: /* ! 3458: ** Return TRUE if the cursor has been moved off of the last ! 3459: ** row of output. ! 3460: */ ! 3461: static int completionEof(sqlite3_vtab_cursor *cur){ ! 3462: completion_cursor *pCur = (completion_cursor*)cur; ! 3463: return pCur->ePhase >= COMPLETION_EOF; ! 3464: } ! 3465: ! 3466: /* ! 3467: ** This method is called to "rewind" the completion_cursor object back ! 3468: ** to the first row of output. This method is always called at least ! 3469: ** once prior to any call to completionColumn() or completionRowid() or ! 3470: ** completionEof(). ! 3471: */ ! 3472: static int completionFilter( ! 3473: sqlite3_vtab_cursor *pVtabCursor, ! 3474: int idxNum, const char *idxStr, ! 3475: int argc, sqlite3_value **argv ! 3476: ){ ! 3477: completion_cursor *pCur = (completion_cursor *)pVtabCursor; ! 3478: int iArg = 0; ! 3479: (void)(idxStr); /* Unused parameter */ ! 3480: (void)(argc); /* Unused parameter */ ! 3481: completionCursorReset(pCur); ! 3482: if( idxNum & 1 ){ ! 3483: pCur->nPrefix = sqlite3_value_bytes(argv[iArg]); ! 3484: if( pCur->nPrefix>0 ){ ! 3485: pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); ! 3486: if( pCur->zPrefix==0 ) return SQLITE_NOMEM; ! 3487: } ! 3488: iArg = 1; ! 3489: } ! 3490: if( idxNum & 2 ){ ! 3491: pCur->nLine = sqlite3_value_bytes(argv[iArg]); ! 3492: if( pCur->nLine>0 ){ ! 3493: pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); ! 3494: if( pCur->zLine==0 ) return SQLITE_NOMEM; ! 3495: } ! 3496: } ! 3497: if( pCur->zLine!=0 && pCur->zPrefix==0 ){ ! 3498: int i = pCur->nLine; ! 3499: while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){ ! 3500: i--; ! 3501: } ! 3502: pCur->nPrefix = pCur->nLine - i; ! 3503: if( pCur->nPrefix>0 ){ ! 3504: pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i); ! 3505: if( pCur->zPrefix==0 ) return SQLITE_NOMEM; ! 3506: } ! 3507: } ! 3508: pCur->iRowid = 0; ! 3509: pCur->ePhase = COMPLETION_FIRST_PHASE; ! 3510: return completionNext(pVtabCursor); ! 3511: } ! 3512: ! 3513: /* ! 3514: ** SQLite will invoke this method one or more times while planning a query ! 3515: ** that uses the completion virtual table. This routine needs to create ! 3516: ** a query plan for each invocation and compute an estimated cost for that ! 3517: ** plan. ! 3518: ** ! 3519: ** There are two hidden parameters that act as arguments to the table-valued ! 3520: ** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix" ! 3521: ** is available and bit 1 is set if "wholeline" is available. ! 3522: */ ! 3523: static int completionBestIndex( ! 3524: sqlite3_vtab *tab, ! 3525: sqlite3_index_info *pIdxInfo ! 3526: ){ ! 3527: int i; /* Loop over constraints */ ! 3528: int idxNum = 0; /* The query plan bitmask */ ! 3529: int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */ ! 3530: int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */ ! 3531: int nArg = 0; /* Number of arguments that completeFilter() expects */ ! 3532: const struct sqlite3_index_constraint *pConstraint; ! 3533: ! 3534: (void)(tab); /* Unused parameter */ ! 3535: pConstraint = pIdxInfo->aConstraint; ! 3536: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ ! 3537: if( pConstraint->usable==0 ) continue; ! 3538: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; ! 3539: switch( pConstraint->iColumn ){ ! 3540: case COMPLETION_COLUMN_PREFIX: ! 3541: prefixIdx = i; ! 3542: idxNum |= 1; ! 3543: break; ! 3544: case COMPLETION_COLUMN_WHOLELINE: ! 3545: wholelineIdx = i; ! 3546: idxNum |= 2; ! 3547: break; ! 3548: } ! 3549: } ! 3550: if( prefixIdx>=0 ){ ! 3551: pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg; ! 3552: pIdxInfo->aConstraintUsage[prefixIdx].omit = 1; ! 3553: } ! 3554: if( wholelineIdx>=0 ){ ! 3555: pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg; ! 3556: pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1; ! 3557: } ! 3558: pIdxInfo->idxNum = idxNum; ! 3559: pIdxInfo->estimatedCost = (double)5000 - 1000*nArg; ! 3560: pIdxInfo->estimatedRows = 500 - 100*nArg; ! 3561: return SQLITE_OK; ! 3562: } ! 3563: ! 3564: /* ! 3565: ** This following structure defines all the methods for the ! 3566: ** completion virtual table. ! 3567: */ ! 3568: static sqlite3_module completionModule = { ! 3569: 0, /* iVersion */ ! 3570: 0, /* xCreate */ ! 3571: completionConnect, /* xConnect */ ! 3572: completionBestIndex, /* xBestIndex */ ! 3573: completionDisconnect, /* xDisconnect */ ! 3574: 0, /* xDestroy */ ! 3575: completionOpen, /* xOpen - open a cursor */ ! 3576: completionClose, /* xClose - close a cursor */ ! 3577: completionFilter, /* xFilter - configure scan constraints */ ! 3578: completionNext, /* xNext - advance a cursor */ ! 3579: completionEof, /* xEof - check for end of scan */ ! 3580: completionColumn, /* xColumn - read data */ ! 3581: completionRowid, /* xRowid - read data */ ! 3582: 0, /* xUpdate */ ! 3583: 0, /* xBegin */ ! 3584: 0, /* xSync */ ! 3585: 0, /* xCommit */ ! 3586: 0, /* xRollback */ ! 3587: 0, /* xFindMethod */ ! 3588: 0, /* xRename */ ! 3589: 0, /* xSavepoint */ ! 3590: 0, /* xRelease */ ! 3591: 0, /* xRollbackTo */ ! 3592: 0 /* xShadowName */ ! 3593: }; ! 3594: ! 3595: #endif /* SQLITE_OMIT_VIRTUALTABLE */ ! 3596: ! 3597: int sqlite3CompletionVtabInit(sqlite3 *db){ ! 3598: int rc = SQLITE_OK; ! 3599: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 3600: rc = sqlite3_create_module(db, "completion", &completionModule, 0); ! 3601: #endif ! 3602: return rc; ! 3603: } ! 3604: ! 3605: #ifdef _WIN32 ! 3606: ! 3607: #endif ! 3608: int sqlite3_completion_init( ! 3609: sqlite3 *db, ! 3610: char **pzErrMsg, ! 3611: const sqlite3_api_routines *pApi ! 3612: ){ ! 3613: int rc = SQLITE_OK; ! 3614: SQLITE_EXTENSION_INIT2(pApi); ! 3615: (void)(pzErrMsg); /* Unused parameter */ ! 3616: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 3617: rc = sqlite3CompletionVtabInit(db); ! 3618: #endif ! 3619: return rc; ! 3620: } ! 3621: ! 3622: /************************* End ../ext/misc/completion.c ********************/ ! 3623: /************************* Begin ../ext/misc/appendvfs.c ******************/ ! 3624: /* ! 3625: ** 2017-10-20 ! 3626: ** ! 3627: ** The author disclaims copyright to this source code. In place of ! 3628: ** a legal notice, here is a blessing: ! 3629: ** ! 3630: ** May you do good and not evil. ! 3631: ** May you find forgiveness for yourself and forgive others. ! 3632: ** May you share freely, never taking more than you give. ! 3633: ** ! 3634: ****************************************************************************** ! 3635: ** ! 3636: ** This file implements a VFS shim that allows an SQLite database to be ! 3637: ** appended onto the end of some other file, such as an executable. ! 3638: ** ! 3639: ** A special record must appear at the end of the file that identifies the ! 3640: ** file as an appended database and provides an offset to page 1. For ! 3641: ** best performance page 1 should be located at a disk page boundary, though ! 3642: ** that is not required. ! 3643: ** ! 3644: ** When opening a database using this VFS, the connection might treat ! 3645: ** the file as an ordinary SQLite database, or it might treat is as a ! 3646: ** database appended onto some other file. Here are the rules: ! 3647: ** ! 3648: ** (1) When opening a new empty file, that file is treated as an ordinary ! 3649: ** database. ! 3650: ** ! 3651: ** (2) When opening a file that begins with the standard SQLite prefix ! 3652: ** string "SQLite format 3", that file is treated as an ordinary ! 3653: ** database. ! 3654: ** ! 3655: ** (3) When opening a file that ends with the appendvfs trailer string ! 3656: ** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended ! 3657: ** database. ! 3658: ** ! 3659: ** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is ! 3660: ** set, then a new database is appended to the already existing file. ! 3661: ** ! 3662: ** (5) Otherwise, SQLITE_CANTOPEN is returned. ! 3663: ** ! 3664: ** To avoid unnecessary complications with the PENDING_BYTE, the size of ! 3665: ** the file containing the database is limited to 1GB. This VFS will refuse ! 3666: ** to read or write past the 1GB mark. This restriction might be lifted in ! 3667: ** future versions. For now, if you need a large database, then keep the ! 3668: ** database in a separate file. ! 3669: ** ! 3670: ** If the file being opened is not an appended database, then this shim is ! 3671: ** a pass-through into the default underlying VFS. ! 3672: **/ ! 3673: /* #include "sqlite3ext.h" */ ! 3674: SQLITE_EXTENSION_INIT1 ! 3675: #include <string.h> ! 3676: #include <assert.h> ! 3677: ! 3678: /* The append mark at the end of the database is: ! 3679: ** ! 3680: ** Start-Of-SQLite3-NNNNNNNN ! 3681: ** 123456789 123456789 12345 ! 3682: ** ! 3683: ** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is ! 3684: ** the offset to page 1. ! 3685: */ ! 3686: #define APND_MARK_PREFIX "Start-Of-SQLite3-" ! 3687: #define APND_MARK_PREFIX_SZ 17 ! 3688: #define APND_MARK_SIZE 25 ! 3689: ! 3690: /* ! 3691: ** Maximum size of the combined prefix + database + append-mark. This ! 3692: ** must be less than 0x40000000 to avoid locking issues on Windows. ! 3693: */ ! 3694: #define APND_MAX_SIZE (65536*15259) ! 3695: ! 3696: /* ! 3697: ** Forward declaration of objects used by this utility ! 3698: */ ! 3699: typedef struct sqlite3_vfs ApndVfs; ! 3700: typedef struct ApndFile ApndFile; ! 3701: ! 3702: /* Access to a lower-level VFS that (might) implement dynamic loading, ! 3703: ** access to randomness, etc. ! 3704: */ ! 3705: #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) ! 3706: #define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1)) ! 3707: ! 3708: /* An open file */ ! 3709: struct ApndFile { ! 3710: sqlite3_file base; /* IO methods */ ! 3711: sqlite3_int64 iPgOne; /* File offset to page 1 */ ! 3712: sqlite3_int64 iMark; /* Start of the append-mark */ ! 3713: }; ! 3714: ! 3715: /* ! 3716: ** Methods for ApndFile ! 3717: */ ! 3718: static int apndClose(sqlite3_file*); ! 3719: static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); ! 3720: static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); ! 3721: static int apndTruncate(sqlite3_file*, sqlite3_int64 size); ! 3722: static int apndSync(sqlite3_file*, int flags); ! 3723: static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize); ! 3724: static int apndLock(sqlite3_file*, int); ! 3725: static int apndUnlock(sqlite3_file*, int); ! 3726: static int apndCheckReservedLock(sqlite3_file*, int *pResOut); ! 3727: static int apndFileControl(sqlite3_file*, int op, void *pArg); ! 3728: static int apndSectorSize(sqlite3_file*); ! 3729: static int apndDeviceCharacteristics(sqlite3_file*); ! 3730: static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**); ! 3731: static int apndShmLock(sqlite3_file*, int offset, int n, int flags); ! 3732: static void apndShmBarrier(sqlite3_file*); ! 3733: static int apndShmUnmap(sqlite3_file*, int deleteFlag); ! 3734: static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); ! 3735: static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); ! 3736: ! 3737: /* ! 3738: ** Methods for ApndVfs ! 3739: */ ! 3740: static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); ! 3741: static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir); ! 3742: static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *); ! 3743: static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); ! 3744: static void *apndDlOpen(sqlite3_vfs*, const char *zFilename); ! 3745: static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg); ! 3746: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); ! 3747: static void apndDlClose(sqlite3_vfs*, void*); ! 3748: static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut); ! 3749: static int apndSleep(sqlite3_vfs*, int microseconds); ! 3750: static int apndCurrentTime(sqlite3_vfs*, double*); ! 3751: static int apndGetLastError(sqlite3_vfs*, int, char *); ! 3752: static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); ! 3753: static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr); ! 3754: static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z); ! 3755: static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName); ! 3756: ! 3757: static sqlite3_vfs apnd_vfs = { ! 3758: 3, /* iVersion (set when registered) */ ! 3759: 0, /* szOsFile (set when registered) */ ! 3760: 1024, /* mxPathname */ ! 3761: 0, /* pNext */ ! 3762: "apndvfs", /* zName */ ! 3763: 0, /* pAppData (set when registered) */ ! 3764: apndOpen, /* xOpen */ ! 3765: apndDelete, /* xDelete */ ! 3766: apndAccess, /* xAccess */ ! 3767: apndFullPathname, /* xFullPathname */ ! 3768: apndDlOpen, /* xDlOpen */ ! 3769: apndDlError, /* xDlError */ ! 3770: apndDlSym, /* xDlSym */ ! 3771: apndDlClose, /* xDlClose */ ! 3772: apndRandomness, /* xRandomness */ ! 3773: apndSleep, /* xSleep */ ! 3774: apndCurrentTime, /* xCurrentTime */ ! 3775: apndGetLastError, /* xGetLastError */ ! 3776: apndCurrentTimeInt64, /* xCurrentTimeInt64 */ ! 3777: apndSetSystemCall, /* xSetSystemCall */ ! 3778: apndGetSystemCall, /* xGetSystemCall */ ! 3779: apndNextSystemCall /* xNextSystemCall */ ! 3780: }; ! 3781: ! 3782: static const sqlite3_io_methods apnd_io_methods = { ! 3783: 3, /* iVersion */ ! 3784: apndClose, /* xClose */ ! 3785: apndRead, /* xRead */ ! 3786: apndWrite, /* xWrite */ ! 3787: apndTruncate, /* xTruncate */ ! 3788: apndSync, /* xSync */ ! 3789: apndFileSize, /* xFileSize */ ! 3790: apndLock, /* xLock */ ! 3791: apndUnlock, /* xUnlock */ ! 3792: apndCheckReservedLock, /* xCheckReservedLock */ ! 3793: apndFileControl, /* xFileControl */ ! 3794: apndSectorSize, /* xSectorSize */ ! 3795: apndDeviceCharacteristics, /* xDeviceCharacteristics */ ! 3796: apndShmMap, /* xShmMap */ ! 3797: apndShmLock, /* xShmLock */ ! 3798: apndShmBarrier, /* xShmBarrier */ ! 3799: apndShmUnmap, /* xShmUnmap */ ! 3800: apndFetch, /* xFetch */ ! 3801: apndUnfetch /* xUnfetch */ ! 3802: }; ! 3803: ! 3804: ! 3805: ! 3806: /* ! 3807: ** Close an apnd-file. ! 3808: */ ! 3809: static int apndClose(sqlite3_file *pFile){ ! 3810: pFile = ORIGFILE(pFile); ! 3811: return pFile->pMethods->xClose(pFile); ! 3812: } ! 3813: ! 3814: /* ! 3815: ** Read data from an apnd-file. ! 3816: */ ! 3817: static int apndRead( ! 3818: sqlite3_file *pFile, ! 3819: void *zBuf, ! 3820: int iAmt, ! 3821: sqlite_int64 iOfst ! 3822: ){ ! 3823: ApndFile *p = (ApndFile *)pFile; ! 3824: pFile = ORIGFILE(pFile); ! 3825: return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne); ! 3826: } ! 3827: ! 3828: /* ! 3829: ** Add the append-mark onto the end of the file. ! 3830: */ ! 3831: static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){ ! 3832: int i; ! 3833: unsigned char a[APND_MARK_SIZE]; ! 3834: memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ); ! 3835: for(i=0; i<8; i++){ ! 3836: a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff; ! 3837: } ! 3838: return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark); ! 3839: } ! 3840: ! 3841: /* ! 3842: ** Write data to an apnd-file. ! 3843: */ ! 3844: static int apndWrite( ! 3845: sqlite3_file *pFile, ! 3846: const void *zBuf, ! 3847: int iAmt, ! 3848: sqlite_int64 iOfst ! 3849: ){ ! 3850: int rc; ! 3851: ApndFile *p = (ApndFile *)pFile; ! 3852: pFile = ORIGFILE(pFile); ! 3853: if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL; ! 3854: rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne); ! 3855: if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){ ! 3856: sqlite3_int64 sz = 0; ! 3857: rc = pFile->pMethods->xFileSize(pFile, &sz); ! 3858: if( rc==SQLITE_OK ){ ! 3859: p->iMark = sz - APND_MARK_SIZE; ! 3860: if( iOfst + iAmt + p->iPgOne > p->iMark ){ ! 3861: p->iMark = p->iPgOne + iOfst + iAmt; ! 3862: rc = apndWriteMark(p, pFile); ! 3863: } ! 3864: } ! 3865: } ! 3866: return rc; ! 3867: } ! 3868: ! 3869: /* ! 3870: ** Truncate an apnd-file. ! 3871: */ ! 3872: static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){ ! 3873: int rc; ! 3874: ApndFile *p = (ApndFile *)pFile; ! 3875: pFile = ORIGFILE(pFile); ! 3876: rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE); ! 3877: if( rc==SQLITE_OK ){ ! 3878: p->iMark = p->iPgOne+size; ! 3879: rc = apndWriteMark(p, pFile); ! 3880: } ! 3881: return rc; ! 3882: } ! 3883: ! 3884: /* ! 3885: ** Sync an apnd-file. ! 3886: */ ! 3887: static int apndSync(sqlite3_file *pFile, int flags){ ! 3888: pFile = ORIGFILE(pFile); ! 3889: return pFile->pMethods->xSync(pFile, flags); ! 3890: } ! 3891: ! 3892: /* ! 3893: ** Return the current file-size of an apnd-file. ! 3894: */ ! 3895: static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ! 3896: ApndFile *p = (ApndFile *)pFile; ! 3897: int rc; ! 3898: pFile = ORIGFILE(p); ! 3899: rc = pFile->pMethods->xFileSize(pFile, pSize); ! 3900: if( rc==SQLITE_OK && p->iPgOne ){ ! 3901: *pSize -= p->iPgOne + APND_MARK_SIZE; ! 3902: } ! 3903: return rc; ! 3904: } ! 3905: ! 3906: /* ! 3907: ** Lock an apnd-file. ! 3908: */ ! 3909: static int apndLock(sqlite3_file *pFile, int eLock){ ! 3910: pFile = ORIGFILE(pFile); ! 3911: return pFile->pMethods->xLock(pFile, eLock); ! 3912: } ! 3913: ! 3914: /* ! 3915: ** Unlock an apnd-file. ! 3916: */ ! 3917: static int apndUnlock(sqlite3_file *pFile, int eLock){ ! 3918: pFile = ORIGFILE(pFile); ! 3919: return pFile->pMethods->xUnlock(pFile, eLock); ! 3920: } ! 3921: ! 3922: /* ! 3923: ** Check if another file-handle holds a RESERVED lock on an apnd-file. ! 3924: */ ! 3925: static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){ ! 3926: pFile = ORIGFILE(pFile); ! 3927: return pFile->pMethods->xCheckReservedLock(pFile, pResOut); ! 3928: } ! 3929: ! 3930: /* ! 3931: ** File control method. For custom operations on an apnd-file. ! 3932: */ ! 3933: static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){ ! 3934: ApndFile *p = (ApndFile *)pFile; ! 3935: int rc; ! 3936: pFile = ORIGFILE(pFile); ! 3937: rc = pFile->pMethods->xFileControl(pFile, op, pArg); ! 3938: if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ ! 3939: *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg); ! 3940: } ! 3941: return rc; ! 3942: } ! 3943: ! 3944: /* ! 3945: ** Return the sector-size in bytes for an apnd-file. ! 3946: */ ! 3947: static int apndSectorSize(sqlite3_file *pFile){ ! 3948: pFile = ORIGFILE(pFile); ! 3949: return pFile->pMethods->xSectorSize(pFile); ! 3950: } ! 3951: ! 3952: /* ! 3953: ** Return the device characteristic flags supported by an apnd-file. ! 3954: */ ! 3955: static int apndDeviceCharacteristics(sqlite3_file *pFile){ ! 3956: pFile = ORIGFILE(pFile); ! 3957: return pFile->pMethods->xDeviceCharacteristics(pFile); ! 3958: } ! 3959: ! 3960: /* Create a shared memory file mapping */ ! 3961: static int apndShmMap( ! 3962: sqlite3_file *pFile, ! 3963: int iPg, ! 3964: int pgsz, ! 3965: int bExtend, ! 3966: void volatile **pp ! 3967: ){ ! 3968: pFile = ORIGFILE(pFile); ! 3969: return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp); ! 3970: } ! 3971: ! 3972: /* Perform locking on a shared-memory segment */ ! 3973: static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){ ! 3974: pFile = ORIGFILE(pFile); ! 3975: return pFile->pMethods->xShmLock(pFile,offset,n,flags); ! 3976: } ! 3977: ! 3978: /* Memory barrier operation on shared memory */ ! 3979: static void apndShmBarrier(sqlite3_file *pFile){ ! 3980: pFile = ORIGFILE(pFile); ! 3981: pFile->pMethods->xShmBarrier(pFile); ! 3982: } ! 3983: ! 3984: /* Unmap a shared memory segment */ ! 3985: static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){ ! 3986: pFile = ORIGFILE(pFile); ! 3987: return pFile->pMethods->xShmUnmap(pFile,deleteFlag); ! 3988: } ! 3989: ! 3990: /* Fetch a page of a memory-mapped file */ ! 3991: static int apndFetch( ! 3992: sqlite3_file *pFile, ! 3993: sqlite3_int64 iOfst, ! 3994: int iAmt, ! 3995: void **pp ! 3996: ){ ! 3997: ApndFile *p = (ApndFile *)pFile; ! 3998: pFile = ORIGFILE(pFile); ! 3999: return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp); ! 4000: } ! 4001: ! 4002: /* Release a memory-mapped page */ ! 4003: static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ ! 4004: ApndFile *p = (ApndFile *)pFile; ! 4005: pFile = ORIGFILE(pFile); ! 4006: return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage); ! 4007: } ! 4008: ! 4009: /* ! 4010: ** Check to see if the file is an ordinary SQLite database file. ! 4011: */ ! 4012: static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){ ! 4013: int rc; ! 4014: char zHdr[16]; ! 4015: static const char aSqliteHdr[] = "SQLite format 3"; ! 4016: if( sz<512 ) return 0; ! 4017: rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0); ! 4018: if( rc ) return 0; ! 4019: return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0; ! 4020: } ! 4021: ! 4022: /* ! 4023: ** Try to read the append-mark off the end of a file. Return the ! 4024: ** start of the appended database if the append-mark is present. If ! 4025: ** there is no append-mark, return -1; ! 4026: */ ! 4027: static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){ ! 4028: int rc, i; ! 4029: sqlite3_int64 iMark; ! 4030: unsigned char a[APND_MARK_SIZE]; ! 4031: ! 4032: if( sz<=APND_MARK_SIZE ) return -1; ! 4033: rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE); ! 4034: if( rc ) return -1; ! 4035: if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1; ! 4036: iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56; ! 4037: for(i=1; i<8; i++){ ! 4038: iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i); ! 4039: } ! 4040: return iMark; ! 4041: } ! 4042: ! 4043: /* ! 4044: ** Open an apnd file handle. ! 4045: */ ! 4046: static int apndOpen( ! 4047: sqlite3_vfs *pVfs, ! 4048: const char *zName, ! 4049: sqlite3_file *pFile, ! 4050: int flags, ! 4051: int *pOutFlags ! 4052: ){ ! 4053: ApndFile *p; ! 4054: sqlite3_file *pSubFile; ! 4055: sqlite3_vfs *pSubVfs; ! 4056: int rc; ! 4057: sqlite3_int64 sz; ! 4058: pSubVfs = ORIGVFS(pVfs); ! 4059: if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ ! 4060: return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags); ! 4061: } ! 4062: p = (ApndFile*)pFile; ! 4063: memset(p, 0, sizeof(*p)); ! 4064: pSubFile = ORIGFILE(pFile); ! 4065: pFile->pMethods = &apnd_io_methods; ! 4066: rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags); ! 4067: if( rc ) goto apnd_open_done; ! 4068: rc = pSubFile->pMethods->xFileSize(pSubFile, &sz); ! 4069: if( rc ){ ! 4070: pSubFile->pMethods->xClose(pSubFile); ! 4071: goto apnd_open_done; ! 4072: } ! 4073: if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){ ! 4074: memmove(pFile, pSubFile, pSubVfs->szOsFile); ! 4075: return SQLITE_OK; ! 4076: } ! 4077: p->iMark = 0; ! 4078: p->iPgOne = apndReadMark(sz, pFile); ! 4079: if( p->iPgOne>0 ){ ! 4080: return SQLITE_OK; ! 4081: } ! 4082: if( (flags & SQLITE_OPEN_CREATE)==0 ){ ! 4083: pSubFile->pMethods->xClose(pSubFile); ! 4084: rc = SQLITE_CANTOPEN; ! 4085: } ! 4086: p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff; ! 4087: apnd_open_done: ! 4088: if( rc ) pFile->pMethods = 0; ! 4089: return rc; ! 4090: } ! 4091: ! 4092: /* ! 4093: ** All other VFS methods are pass-thrus. ! 4094: */ ! 4095: static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ! 4096: return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync); ! 4097: } ! 4098: static int apndAccess( ! 4099: sqlite3_vfs *pVfs, ! 4100: const char *zPath, ! 4101: int flags, ! 4102: int *pResOut ! 4103: ){ ! 4104: return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut); ! 4105: } ! 4106: static int apndFullPathname( ! 4107: sqlite3_vfs *pVfs, ! 4108: const char *zPath, ! 4109: int nOut, ! 4110: char *zOut ! 4111: ){ ! 4112: return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut); ! 4113: } ! 4114: static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){ ! 4115: return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); ! 4116: } ! 4117: static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ ! 4118: ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); ! 4119: } ! 4120: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ ! 4121: return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); ! 4122: } ! 4123: static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){ ! 4124: ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); ! 4125: } ! 4126: static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ ! 4127: return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); ! 4128: } ! 4129: static int apndSleep(sqlite3_vfs *pVfs, int nMicro){ ! 4130: return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); ! 4131: } ! 4132: static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ ! 4133: return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); ! 4134: } ! 4135: static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){ ! 4136: return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); ! 4137: } ! 4138: static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ ! 4139: return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); ! 4140: } ! 4141: static int apndSetSystemCall( ! 4142: sqlite3_vfs *pVfs, ! 4143: const char *zName, ! 4144: sqlite3_syscall_ptr pCall ! 4145: ){ ! 4146: return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall); ! 4147: } ! 4148: static sqlite3_syscall_ptr apndGetSystemCall( ! 4149: sqlite3_vfs *pVfs, ! 4150: const char *zName ! 4151: ){ ! 4152: return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName); ! 4153: } ! 4154: static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){ ! 4155: return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName); ! 4156: } ! 4157: ! 4158: ! 4159: #ifdef _WIN32 ! 4160: ! 4161: #endif ! 4162: /* ! 4163: ** This routine is called when the extension is loaded. ! 4164: ** Register the new VFS. ! 4165: */ ! 4166: int sqlite3_appendvfs_init( ! 4167: sqlite3 *db, ! 4168: char **pzErrMsg, ! 4169: const sqlite3_api_routines *pApi ! 4170: ){ ! 4171: int rc = SQLITE_OK; ! 4172: sqlite3_vfs *pOrig; ! 4173: SQLITE_EXTENSION_INIT2(pApi); ! 4174: (void)pzErrMsg; ! 4175: (void)db; ! 4176: pOrig = sqlite3_vfs_find(0); ! 4177: apnd_vfs.iVersion = pOrig->iVersion; ! 4178: apnd_vfs.pAppData = pOrig; ! 4179: apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); ! 4180: rc = sqlite3_vfs_register(&apnd_vfs, 0); ! 4181: #ifdef APPENDVFS_TEST ! 4182: if( rc==SQLITE_OK ){ ! 4183: rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); ! 4184: } ! 4185: #endif ! 4186: if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; ! 4187: return rc; ! 4188: } ! 4189: ! 4190: /************************* End ../ext/misc/appendvfs.c ********************/ ! 4191: /************************* Begin ../ext/misc/memtrace.c ******************/ ! 4192: /* ! 4193: ** 2019-01-21 ! 4194: ** ! 4195: ** The author disclaims copyright to this source code. In place of ! 4196: ** a legal notice, here is a blessing: ! 4197: ** ! 4198: ** May you do good and not evil. ! 4199: ** May you find forgiveness for yourself and forgive others. ! 4200: ** May you share freely, never taking more than you give. ! 4201: ** ! 4202: ************************************************************************* ! 4203: ** ! 4204: ** This file implements an extension that uses the SQLITE_CONFIG_MALLOC ! 4205: ** mechanism to add a tracing layer on top of SQLite. If this extension ! 4206: ** is registered prior to sqlite3_initialize(), it will cause all memory ! 4207: ** allocation activities to be logged on standard output, or to some other ! 4208: ** FILE specified by the initializer. ! 4209: ** ! 4210: ** This file needs to be compiled into the application that uses it. ! 4211: ** ! 4212: ** This extension is used to implement the --memtrace option of the ! 4213: ** command-line shell. ! 4214: */ ! 4215: #include <assert.h> ! 4216: #include <string.h> ! 4217: #include <stdio.h> ! 4218: ! 4219: /* The original memory allocation routines */ ! 4220: static sqlite3_mem_methods memtraceBase; ! 4221: static FILE *memtraceOut; ! 4222: ! 4223: /* Methods that trace memory allocations */ ! 4224: static void *memtraceMalloc(int n){ ! 4225: if( memtraceOut ){ ! 4226: fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", ! 4227: memtraceBase.xRoundup(n)); ! 4228: } ! 4229: return memtraceBase.xMalloc(n); ! 4230: } ! 4231: static void memtraceFree(void *p){ ! 4232: if( p==0 ) return; ! 4233: if( memtraceOut ){ ! 4234: fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); ! 4235: } ! 4236: memtraceBase.xFree(p); ! 4237: } ! 4238: static void *memtraceRealloc(void *p, int n){ ! 4239: if( p==0 ) return memtraceMalloc(n); ! 4240: if( n==0 ){ ! 4241: memtraceFree(p); ! 4242: return 0; ! 4243: } ! 4244: if( memtraceOut ){ ! 4245: fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", ! 4246: memtraceBase.xSize(p), memtraceBase.xRoundup(n)); ! 4247: } ! 4248: return memtraceBase.xRealloc(p, n); ! 4249: } ! 4250: static int memtraceSize(void *p){ ! 4251: return memtraceBase.xSize(p); ! 4252: } ! 4253: static int memtraceRoundup(int n){ ! 4254: return memtraceBase.xRoundup(n); ! 4255: } ! 4256: static int memtraceInit(void *p){ ! 4257: return memtraceBase.xInit(p); ! 4258: } ! 4259: static void memtraceShutdown(void *p){ ! 4260: memtraceBase.xShutdown(p); ! 4261: } ! 4262: ! 4263: /* The substitute memory allocator */ ! 4264: static sqlite3_mem_methods ersaztMethods = { ! 4265: memtraceMalloc, ! 4266: memtraceFree, ! 4267: memtraceRealloc, ! 4268: memtraceSize, ! 4269: memtraceRoundup, ! 4270: memtraceInit, ! 4271: memtraceShutdown, ! 4272: 0 ! 4273: }; ! 4274: ! 4275: /* Begin tracing memory allocations to out. */ ! 4276: int sqlite3MemTraceActivate(FILE *out){ ! 4277: int rc = SQLITE_OK; ! 4278: if( memtraceBase.xMalloc==0 ){ ! 4279: rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); ! 4280: if( rc==SQLITE_OK ){ ! 4281: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); ! 4282: } ! 4283: } ! 4284: memtraceOut = out; ! 4285: return rc; ! 4286: } ! 4287: ! 4288: /* Deactivate memory tracing */ ! 4289: int sqlite3MemTraceDeactivate(void){ ! 4290: int rc = SQLITE_OK; ! 4291: if( memtraceBase.xMalloc!=0 ){ ! 4292: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); ! 4293: if( rc==SQLITE_OK ){ ! 4294: memset(&memtraceBase, 0, sizeof(memtraceBase)); ! 4295: } ! 4296: } ! 4297: memtraceOut = 0; ! 4298: return rc; ! 4299: } ! 4300: ! 4301: /************************* End ../ext/misc/memtrace.c ********************/ ! 4302: /************************* Begin ../ext/misc/uint.c ******************/ ! 4303: /* ! 4304: ** 2020-04-14 ! 4305: ** ! 4306: ** The author disclaims copyright to this source code. In place of ! 4307: ** a legal notice, here is a blessing: ! 4308: ** ! 4309: ** May you do good and not evil. ! 4310: ** May you find forgiveness for yourself and forgive others. ! 4311: ** May you share freely, never taking more than you give. ! 4312: ** ! 4313: ****************************************************************************** ! 4314: ** ! 4315: ** This SQLite extension implements the UINT collating sequence. ! 4316: ** ! 4317: ** UINT works like BINARY for text, except that embedded strings ! 4318: ** of digits compare in numeric order. ! 4319: ** ! 4320: ** * Leading zeros are handled properly, in the sense that ! 4321: ** they do not mess of the maginitude comparison of embedded ! 4322: ** strings of digits. "x00123y" is equal to "x123y". ! 4323: ** ! 4324: ** * Only unsigned integers are recognized. Plus and minus ! 4325: ** signs are ignored. Decimal points and exponential notation ! 4326: ** are ignored. ! 4327: ** ! 4328: ** * Embedded integers can be of arbitrary length. Comparison ! 4329: ** is *not* limited integers that can be expressed as a ! 4330: ** 64-bit machine integer. ! 4331: */ ! 4332: /* #include "sqlite3ext.h" */ ! 4333: SQLITE_EXTENSION_INIT1 ! 4334: #include <assert.h> ! 4335: #include <string.h> ! 4336: #include <ctype.h> ! 4337: ! 4338: /* ! 4339: ** Compare text in lexicographic order, except strings of digits ! 4340: ** compare in numeric order. ! 4341: */ ! 4342: static int uintCollFunc( ! 4343: void *notUsed, ! 4344: int nKey1, const void *pKey1, ! 4345: int nKey2, const void *pKey2 ! 4346: ){ ! 4347: const unsigned char *zA = (const unsigned char*)pKey1; ! 4348: const unsigned char *zB = (const unsigned char*)pKey2; ! 4349: int i=0, j=0, x; ! 4350: (void)notUsed; ! 4351: while( i<nKey1 && j<nKey2 ){ ! 4352: x = zA[i] - zB[j]; ! 4353: if( isdigit(zA[i]) ){ ! 4354: int k; ! 4355: if( !isdigit(zB[j]) ) return x; ! 4356: while( i<nKey1 && zA[i]=='0' ){ i++; } ! 4357: while( j<nKey2 && zB[j]=='0' ){ j++; } ! 4358: k = 0; ! 4359: while( i+k<nKey1 && isdigit(zA[i+k]) ! 4360: && j+k<nKey2 && isdigit(zB[j+k]) ){ ! 4361: k++; ! 4362: } ! 4363: if( i+k<nKey1 && isdigit(zA[i+k]) ){ ! 4364: return +1; ! 4365: }else if( j+k<nKey2 && isdigit(zB[j+k]) ){ ! 4366: return -1; ! 4367: }else{ ! 4368: x = memcmp(zA+i, zB+j, k); ! 4369: if( x ) return x; ! 4370: i += k; ! 4371: j += k; ! 4372: } ! 4373: }else if( x ){ ! 4374: return x; ! 4375: }else{ ! 4376: i++; ! 4377: j++; ! 4378: } ! 4379: } ! 4380: return (nKey1 - i) - (nKey2 - j); ! 4381: } ! 4382: ! 4383: #ifdef _WIN32 ! 4384: ! 4385: #endif ! 4386: int sqlite3_uint_init( ! 4387: sqlite3 *db, ! 4388: char **pzErrMsg, ! 4389: const sqlite3_api_routines *pApi ! 4390: ){ ! 4391: SQLITE_EXTENSION_INIT2(pApi); ! 4392: (void)pzErrMsg; /* Unused parameter */ ! 4393: return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc); ! 4394: } ! 4395: ! 4396: /************************* End ../ext/misc/uint.c ********************/ ! 4397: /************************* Begin ../ext/misc/decimal.c ******************/ ! 4398: /* ! 4399: ** 2020-06-22 ! 4400: ** ! 4401: ** The author disclaims copyright to this source code. In place of ! 4402: ** a legal notice, here is a blessing: ! 4403: ** ! 4404: ** May you do good and not evil. ! 4405: ** May you find forgiveness for yourself and forgive others. ! 4406: ** May you share freely, never taking more than you give. ! 4407: ** ! 4408: ****************************************************************************** ! 4409: ** ! 4410: ** Routines to implement arbitrary-precision decimal math. ! 4411: ** ! 4412: ** The focus here is on simplicity and correctness, not performance. ! 4413: */ ! 4414: /* #include "sqlite3ext.h" */ ! 4415: SQLITE_EXTENSION_INIT1 ! 4416: #include <assert.h> ! 4417: #include <string.h> ! 4418: #include <ctype.h> ! 4419: #include <stdlib.h> ! 4420: ! 4421: /* Mark a function parameter as unused, to suppress nuisance compiler ! 4422: ** warnings. */ ! 4423: #ifndef UNUSED_PARAMETER ! 4424: # define UNUSED_PARAMETER(X) (void)(X) ! 4425: #endif ! 4426: ! 4427: ! 4428: /* A decimal object */ ! 4429: typedef struct Decimal Decimal; ! 4430: struct Decimal { ! 4431: char sign; /* 0 for positive, 1 for negative */ ! 4432: char oom; /* True if an OOM is encountered */ ! 4433: char isNull; /* True if holds a NULL rather than a number */ ! 4434: char isInit; /* True upon initialization */ ! 4435: int nDigit; /* Total number of digits */ ! 4436: int nFrac; /* Number of digits to the right of the decimal point */ ! 4437: signed char *a; /* Array of digits. Most significant first. */ ! 4438: }; ! 4439: ! 4440: /* ! 4441: ** Release memory held by a Decimal, but do not free the object itself. ! 4442: */ ! 4443: static void decimal_clear(Decimal *p){ ! 4444: sqlite3_free(p->a); ! 4445: } ! 4446: ! 4447: /* ! 4448: ** Destroy a Decimal object ! 4449: */ ! 4450: static void decimal_free(Decimal *p){ ! 4451: if( p ){ ! 4452: decimal_clear(p); ! 4453: sqlite3_free(p); ! 4454: } ! 4455: } ! 4456: ! 4457: /* ! 4458: ** Allocate a new Decimal object. Initialize it to the number given ! 4459: ** by the input string. ! 4460: */ ! 4461: static Decimal *decimal_new( ! 4462: sqlite3_context *pCtx, ! 4463: sqlite3_value *pIn, ! 4464: int nAlt, ! 4465: const unsigned char *zAlt ! 4466: ){ ! 4467: Decimal *p; ! 4468: int n, i; ! 4469: const unsigned char *zIn; ! 4470: int iExp = 0; ! 4471: p = sqlite3_malloc( sizeof(*p) ); ! 4472: if( p==0 ) goto new_no_mem; ! 4473: p->sign = 0; ! 4474: p->oom = 0; ! 4475: p->isInit = 1; ! 4476: p->isNull = 0; ! 4477: p->nDigit = 0; ! 4478: p->nFrac = 0; ! 4479: if( zAlt ){ ! 4480: n = nAlt, ! 4481: zIn = zAlt; ! 4482: }else{ ! 4483: if( sqlite3_value_type(pIn)==SQLITE_NULL ){ ! 4484: p->a = 0; ! 4485: p->isNull = 1; ! 4486: return p; ! 4487: } ! 4488: n = sqlite3_value_bytes(pIn); ! 4489: zIn = sqlite3_value_text(pIn); ! 4490: } ! 4491: p->a = sqlite3_malloc64( n+1 ); ! 4492: if( p->a==0 ) goto new_no_mem; ! 4493: for(i=0; isspace(zIn[i]); i++){} ! 4494: if( zIn[i]=='-' ){ ! 4495: p->sign = 1; ! 4496: i++; ! 4497: }else if( zIn[i]=='+' ){ ! 4498: i++; ! 4499: } ! 4500: while( i<n && zIn[i]=='0' ) i++; ! 4501: while( i<n ){ ! 4502: char c = zIn[i]; ! 4503: if( c>='0' && c<='9' ){ ! 4504: p->a[p->nDigit++] = c - '0'; ! 4505: }else if( c=='.' ){ ! 4506: p->nFrac = p->nDigit + 1; ! 4507: }else if( c=='e' || c=='E' ){ ! 4508: int j = i+1; ! 4509: int neg = 0; ! 4510: if( j>=n ) break; ! 4511: if( zIn[j]=='-' ){ ! 4512: neg = 1; ! 4513: j++; ! 4514: }else if( zIn[j]=='+' ){ ! 4515: j++; ! 4516: } ! 4517: while( j<n && iExp<1000000 ){ ! 4518: if( zIn[j]>='0' && zIn[j]<='9' ){ ! 4519: iExp = iExp*10 + zIn[j] - '0'; ! 4520: } ! 4521: j++; ! 4522: } ! 4523: if( neg ) iExp = -iExp; ! 4524: break; ! 4525: } ! 4526: i++; ! 4527: } ! 4528: if( p->nFrac ){ ! 4529: p->nFrac = p->nDigit - (p->nFrac - 1); ! 4530: } ! 4531: if( iExp>0 ){ ! 4532: if( p->nFrac>0 ){ ! 4533: if( iExp<=p->nFrac ){ ! 4534: p->nFrac -= iExp; ! 4535: iExp = 0; ! 4536: }else{ ! 4537: iExp -= p->nFrac; ! 4538: p->nFrac = 0; ! 4539: } ! 4540: } ! 4541: if( iExp>0 ){ ! 4542: p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); ! 4543: if( p->a==0 ) goto new_no_mem; ! 4544: memset(p->a+p->nDigit, 0, iExp); ! 4545: p->nDigit += iExp; ! 4546: } ! 4547: }else if( iExp<0 ){ ! 4548: int nExtra; ! 4549: iExp = -iExp; ! 4550: nExtra = p->nDigit - p->nFrac - 1; ! 4551: if( nExtra ){ ! 4552: if( nExtra>=iExp ){ ! 4553: p->nFrac += iExp; ! 4554: iExp = 0; ! 4555: }else{ ! 4556: iExp -= nExtra; ! 4557: p->nFrac = p->nDigit - 1; ! 4558: } ! 4559: } ! 4560: if( iExp>0 ){ ! 4561: p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); ! 4562: if( p->a==0 ) goto new_no_mem; ! 4563: memmove(p->a+iExp, p->a, p->nDigit); ! 4564: memset(p->a, 0, iExp); ! 4565: p->nDigit += iExp; ! 4566: p->nFrac += iExp; ! 4567: } ! 4568: } ! 4569: return p; ! 4570: ! 4571: new_no_mem: ! 4572: if( pCtx ) sqlite3_result_error_nomem(pCtx); ! 4573: sqlite3_free(p); ! 4574: return 0; ! 4575: } ! 4576: ! 4577: /* ! 4578: ** Make the given Decimal the result. ! 4579: */ ! 4580: static void decimal_result(sqlite3_context *pCtx, Decimal *p){ ! 4581: char *z; ! 4582: int i, j; ! 4583: int n; ! 4584: if( p==0 || p->oom ){ ! 4585: sqlite3_result_error_nomem(pCtx); ! 4586: return; ! 4587: } ! 4588: if( p->isNull ){ ! 4589: sqlite3_result_null(pCtx); ! 4590: return; ! 4591: } ! 4592: z = sqlite3_malloc( p->nDigit+4 ); ! 4593: if( z==0 ){ ! 4594: sqlite3_result_error_nomem(pCtx); ! 4595: return; ! 4596: } ! 4597: i = 0; ! 4598: if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){ ! 4599: p->sign = 0; ! 4600: } ! 4601: if( p->sign ){ ! 4602: z[0] = '-'; ! 4603: i = 1; ! 4604: } ! 4605: n = p->nDigit - p->nFrac; ! 4606: if( n<=0 ){ ! 4607: z[i++] = '0'; ! 4608: } ! 4609: j = 0; ! 4610: while( n>1 && p->a[j]==0 ){ ! 4611: j++; ! 4612: n--; ! 4613: } ! 4614: while( n>0 ){ ! 4615: z[i++] = p->a[j] + '0'; ! 4616: j++; ! 4617: n--; ! 4618: } ! 4619: if( p->nFrac ){ ! 4620: z[i++] = '.'; ! 4621: do{ ! 4622: z[i++] = p->a[j] + '0'; ! 4623: j++; ! 4624: }while( j<p->nDigit ); ! 4625: } ! 4626: z[i] = 0; ! 4627: sqlite3_result_text(pCtx, z, i, sqlite3_free); ! 4628: } ! 4629: ! 4630: /* ! 4631: ** SQL Function: decimal(X) ! 4632: ** ! 4633: ** Convert input X into decimal and then back into text ! 4634: */ ! 4635: static void decimalFunc( ! 4636: sqlite3_context *context, ! 4637: int argc, ! 4638: sqlite3_value **argv ! 4639: ){ ! 4640: Decimal *p = decimal_new(context, argv[0], 0, 0); ! 4641: UNUSED_PARAMETER(argc); ! 4642: decimal_result(context, p); ! 4643: decimal_free(p); ! 4644: } ! 4645: ! 4646: /* ! 4647: ** Compare to Decimal objects. Return negative, 0, or positive if the ! 4648: ** first object is less than, equal to, or greater than the second. ! 4649: ** ! 4650: ** Preconditions for this routine: ! 4651: ** ! 4652: ** pA!=0 ! 4653: ** pA->isNull==0 ! 4654: ** pB!=0 ! 4655: ** pB->isNull==0 ! 4656: */ ! 4657: static int decimal_cmp(const Decimal *pA, const Decimal *pB){ ! 4658: int nASig, nBSig, rc, n; ! 4659: if( pA->sign!=pB->sign ){ ! 4660: return pA->sign ? -1 : +1; ! 4661: } ! 4662: if( pA->sign ){ ! 4663: const Decimal *pTemp = pA; ! 4664: pA = pB; ! 4665: pB = pTemp; ! 4666: } ! 4667: nASig = pA->nDigit - pA->nFrac; ! 4668: nBSig = pB->nDigit - pB->nFrac; ! 4669: if( nASig!=nBSig ){ ! 4670: return nASig - nBSig; ! 4671: } ! 4672: n = pA->nDigit; ! 4673: if( n>pB->nDigit ) n = pB->nDigit; ! 4674: rc = memcmp(pA->a, pB->a, n); ! 4675: if( rc==0 ){ ! 4676: rc = pA->nDigit - pB->nDigit; ! 4677: } ! 4678: return rc; ! 4679: } ! 4680: ! 4681: /* ! 4682: ** SQL Function: decimal_cmp(X, Y) ! 4683: ** ! 4684: ** Return negative, zero, or positive if X is less then, equal to, or ! 4685: ** greater than Y. ! 4686: */ ! 4687: static void decimalCmpFunc( ! 4688: sqlite3_context *context, ! 4689: int argc, ! 4690: sqlite3_value **argv ! 4691: ){ ! 4692: Decimal *pA = 0, *pB = 0; ! 4693: int rc; ! 4694: ! 4695: UNUSED_PARAMETER(argc); ! 4696: pA = decimal_new(context, argv[0], 0, 0); ! 4697: if( pA==0 || pA->isNull ) goto cmp_done; ! 4698: pB = decimal_new(context, argv[1], 0, 0); ! 4699: if( pB==0 || pB->isNull ) goto cmp_done; ! 4700: rc = decimal_cmp(pA, pB); ! 4701: if( rc<0 ) rc = -1; ! 4702: else if( rc>0 ) rc = +1; ! 4703: sqlite3_result_int(context, rc); ! 4704: cmp_done: ! 4705: decimal_free(pA); ! 4706: decimal_free(pB); ! 4707: } ! 4708: ! 4709: /* ! 4710: ** Expand the Decimal so that it has a least nDigit digits and nFrac ! 4711: ** digits to the right of the decimal point. ! 4712: */ ! 4713: static void decimal_expand(Decimal *p, int nDigit, int nFrac){ ! 4714: int nAddSig; ! 4715: int nAddFrac; ! 4716: if( p==0 ) return; ! 4717: nAddFrac = nFrac - p->nFrac; ! 4718: nAddSig = (nDigit - p->nDigit) - nAddFrac; ! 4719: if( nAddFrac==0 && nAddSig==0 ) return; ! 4720: p->a = sqlite3_realloc64(p->a, nDigit+1); ! 4721: if( p->a==0 ){ ! 4722: p->oom = 1; ! 4723: return; ! 4724: } ! 4725: if( nAddSig ){ ! 4726: memmove(p->a+nAddSig, p->a, p->nDigit); ! 4727: memset(p->a, 0, nAddSig); ! 4728: p->nDigit += nAddSig; ! 4729: } ! 4730: if( nAddFrac ){ ! 4731: memset(p->a+p->nDigit, 0, nAddFrac); ! 4732: p->nDigit += nAddFrac; ! 4733: p->nFrac += nAddFrac; ! 4734: } ! 4735: } ! 4736: ! 4737: /* ! 4738: ** Add the value pB into pA. ! 4739: ** ! 4740: ** Both pA and pB might become denormalized by this routine. ! 4741: */ ! 4742: static void decimal_add(Decimal *pA, Decimal *pB){ ! 4743: int nSig, nFrac, nDigit; ! 4744: int i, rc; ! 4745: if( pA==0 ){ ! 4746: return; ! 4747: } ! 4748: if( pA->oom || pB==0 || pB->oom ){ ! 4749: pA->oom = 1; ! 4750: return; ! 4751: } ! 4752: if( pA->isNull || pB->isNull ){ ! 4753: pA->isNull = 1; ! 4754: return; ! 4755: } ! 4756: nSig = pA->nDigit - pA->nFrac; ! 4757: if( nSig && pA->a[0]==0 ) nSig--; ! 4758: if( nSig<pB->nDigit-pB->nFrac ){ ! 4759: nSig = pB->nDigit - pB->nFrac; ! 4760: } ! 4761: nFrac = pA->nFrac; ! 4762: if( nFrac<pB->nFrac ) nFrac = pB->nFrac; ! 4763: nDigit = nSig + nFrac + 1; ! 4764: decimal_expand(pA, nDigit, nFrac); ! 4765: decimal_expand(pB, nDigit, nFrac); ! 4766: if( pA->oom || pB->oom ){ ! 4767: pA->oom = 1; ! 4768: }else{ ! 4769: if( pA->sign==pB->sign ){ ! 4770: int carry = 0; ! 4771: for(i=nDigit-1; i>=0; i--){ ! 4772: int x = pA->a[i] + pB->a[i] + carry; ! 4773: if( x>=10 ){ ! 4774: carry = 1; ! 4775: pA->a[i] = x - 10; ! 4776: }else{ ! 4777: carry = 0; ! 4778: pA->a[i] = x; ! 4779: } ! 4780: } ! 4781: }else{ ! 4782: signed char *aA, *aB; ! 4783: int borrow = 0; ! 4784: rc = memcmp(pA->a, pB->a, nDigit); ! 4785: if( rc<0 ){ ! 4786: aA = pB->a; ! 4787: aB = pA->a; ! 4788: pA->sign = !pA->sign; ! 4789: }else{ ! 4790: aA = pA->a; ! 4791: aB = pB->a; ! 4792: } ! 4793: for(i=nDigit-1; i>=0; i--){ ! 4794: int x = aA[i] - aB[i] - borrow; ! 4795: if( x<0 ){ ! 4796: pA->a[i] = x+10; ! 4797: borrow = 1; ! 4798: }else{ ! 4799: pA->a[i] = x; ! 4800: borrow = 0; ! 4801: } ! 4802: } ! 4803: } ! 4804: } ! 4805: } ! 4806: ! 4807: /* ! 4808: ** Compare text in decimal order. ! 4809: */ ! 4810: static int decimalCollFunc( ! 4811: void *notUsed, ! 4812: int nKey1, const void *pKey1, ! 4813: int nKey2, const void *pKey2 ! 4814: ){ ! 4815: const unsigned char *zA = (const unsigned char*)pKey1; ! 4816: const unsigned char *zB = (const unsigned char*)pKey2; ! 4817: Decimal *pA = decimal_new(0, 0, nKey1, zA); ! 4818: Decimal *pB = decimal_new(0, 0, nKey2, zB); ! 4819: int rc; ! 4820: UNUSED_PARAMETER(notUsed); ! 4821: if( pA==0 || pB==0 ){ ! 4822: rc = 0; ! 4823: }else{ ! 4824: rc = decimal_cmp(pA, pB); ! 4825: } ! 4826: decimal_free(pA); ! 4827: decimal_free(pB); ! 4828: return rc; ! 4829: } ! 4830: ! 4831: ! 4832: /* ! 4833: ** SQL Function: decimal_add(X, Y) ! 4834: ** decimal_sub(X, Y) ! 4835: ** ! 4836: ** Return the sum or difference of X and Y. ! 4837: */ ! 4838: static void decimalAddFunc( ! 4839: sqlite3_context *context, ! 4840: int argc, ! 4841: sqlite3_value **argv ! 4842: ){ ! 4843: Decimal *pA = decimal_new(context, argv[0], 0, 0); ! 4844: Decimal *pB = decimal_new(context, argv[1], 0, 0); ! 4845: UNUSED_PARAMETER(argc); ! 4846: decimal_add(pA, pB); ! 4847: decimal_result(context, pA); ! 4848: decimal_free(pA); ! 4849: decimal_free(pB); ! 4850: } ! 4851: static void decimalSubFunc( ! 4852: sqlite3_context *context, ! 4853: int argc, ! 4854: sqlite3_value **argv ! 4855: ){ ! 4856: Decimal *pA = decimal_new(context, argv[0], 0, 0); ! 4857: Decimal *pB = decimal_new(context, argv[1], 0, 0); ! 4858: UNUSED_PARAMETER(argc); ! 4859: if( pB==0 ) return; ! 4860: pB->sign = !pB->sign; ! 4861: decimal_add(pA, pB); ! 4862: decimal_result(context, pA); ! 4863: decimal_free(pA); ! 4864: decimal_free(pB); ! 4865: } ! 4866: ! 4867: /* Aggregate funcion: decimal_sum(X) ! 4868: ** ! 4869: ** Works like sum() except that it uses decimal arithmetic for unlimited ! 4870: ** precision. ! 4871: */ ! 4872: static void decimalSumStep( ! 4873: sqlite3_context *context, ! 4874: int argc, ! 4875: sqlite3_value **argv ! 4876: ){ ! 4877: Decimal *p; ! 4878: Decimal *pArg; ! 4879: UNUSED_PARAMETER(argc); ! 4880: p = sqlite3_aggregate_context(context, sizeof(*p)); ! 4881: if( p==0 ) return; ! 4882: if( !p->isInit ){ ! 4883: p->isInit = 1; ! 4884: p->a = sqlite3_malloc(2); ! 4885: if( p->a==0 ){ ! 4886: p->oom = 1; ! 4887: }else{ ! 4888: p->a[0] = 0; ! 4889: } ! 4890: p->nDigit = 1; ! 4891: p->nFrac = 0; ! 4892: } ! 4893: if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; ! 4894: pArg = decimal_new(context, argv[0], 0, 0); ! 4895: decimal_add(p, pArg); ! 4896: decimal_free(pArg); ! 4897: } ! 4898: static void decimalSumInverse( ! 4899: sqlite3_context *context, ! 4900: int argc, ! 4901: sqlite3_value **argv ! 4902: ){ ! 4903: Decimal *p; ! 4904: Decimal *pArg; ! 4905: UNUSED_PARAMETER(argc); ! 4906: p = sqlite3_aggregate_context(context, sizeof(*p)); ! 4907: if( p==0 ) return; ! 4908: if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; ! 4909: pArg = decimal_new(context, argv[0], 0, 0); ! 4910: if( pArg ) pArg->sign = !pArg->sign; ! 4911: decimal_add(p, pArg); ! 4912: decimal_free(pArg); ! 4913: } ! 4914: static void decimalSumValue(sqlite3_context *context){ ! 4915: Decimal *p = sqlite3_aggregate_context(context, 0); ! 4916: if( p==0 ) return; ! 4917: decimal_result(context, p); ! 4918: } ! 4919: static void decimalSumFinalize(sqlite3_context *context){ ! 4920: Decimal *p = sqlite3_aggregate_context(context, 0); ! 4921: if( p==0 ) return; ! 4922: decimal_result(context, p); ! 4923: decimal_clear(p); ! 4924: } ! 4925: ! 4926: /* ! 4927: ** SQL Function: decimal_mul(X, Y) ! 4928: ** ! 4929: ** Return the product of X and Y. ! 4930: ** ! 4931: ** All significant digits after the decimal point are retained. ! 4932: ** Trailing zeros after the decimal point are omitted as long as ! 4933: ** the number of digits after the decimal point is no less than ! 4934: ** either the number of digits in either input. ! 4935: */ ! 4936: static void decimalMulFunc( ! 4937: sqlite3_context *context, ! 4938: int argc, ! 4939: sqlite3_value **argv ! 4940: ){ ! 4941: Decimal *pA = decimal_new(context, argv[0], 0, 0); ! 4942: Decimal *pB = decimal_new(context, argv[1], 0, 0); ! 4943: signed char *acc = 0; ! 4944: int i, j, k; ! 4945: int minFrac; ! 4946: UNUSED_PARAMETER(argc); ! 4947: if( pA==0 || pA->oom || pA->isNull ! 4948: || pB==0 || pB->oom || pB->isNull ! 4949: ){ ! 4950: goto mul_end; ! 4951: } ! 4952: acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 ); ! 4953: if( acc==0 ){ ! 4954: sqlite3_result_error_nomem(context); ! 4955: goto mul_end; ! 4956: } ! 4957: memset(acc, 0, pA->nDigit + pB->nDigit + 2); ! 4958: minFrac = pA->nFrac; ! 4959: if( pB->nFrac<minFrac ) minFrac = pB->nFrac; ! 4960: for(i=pA->nDigit-1; i>=0; i--){ ! 4961: signed char f = pA->a[i]; ! 4962: int carry = 0, x; ! 4963: for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){ ! 4964: x = acc[k] + f*pB->a[j] + carry; ! 4965: acc[k] = x%10; ! 4966: carry = x/10; ! 4967: } ! 4968: x = acc[k] + carry; ! 4969: acc[k] = x%10; ! 4970: acc[k-1] += x/10; ! 4971: } ! 4972: sqlite3_free(pA->a); ! 4973: pA->a = acc; ! 4974: acc = 0; ! 4975: pA->nDigit += pB->nDigit + 2; ! 4976: pA->nFrac += pB->nFrac; ! 4977: pA->sign ^= pB->sign; ! 4978: while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){ ! 4979: pA->nFrac--; ! 4980: pA->nDigit--; ! 4981: } ! 4982: decimal_result(context, pA); ! 4983: ! 4984: mul_end: ! 4985: sqlite3_free(acc); ! 4986: decimal_free(pA); ! 4987: decimal_free(pB); ! 4988: } ! 4989: ! 4990: #ifdef _WIN32 ! 4991: ! 4992: #endif ! 4993: int sqlite3_decimal_init( ! 4994: sqlite3 *db, ! 4995: char **pzErrMsg, ! 4996: const sqlite3_api_routines *pApi ! 4997: ){ ! 4998: int rc = SQLITE_OK; ! 4999: static const struct { ! 5000: const char *zFuncName; ! 5001: int nArg; ! 5002: void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ! 5003: } aFunc[] = { ! 5004: { "decimal", 1, decimalFunc }, ! 5005: { "decimal_cmp", 2, decimalCmpFunc }, ! 5006: { "decimal_add", 2, decimalAddFunc }, ! 5007: { "decimal_sub", 2, decimalSubFunc }, ! 5008: { "decimal_mul", 2, decimalMulFunc }, ! 5009: }; ! 5010: unsigned int i; ! 5011: (void)pzErrMsg; /* Unused parameter */ ! 5012: ! 5013: SQLITE_EXTENSION_INIT2(pApi); ! 5014: ! 5015: for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ! 5016: rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg, ! 5017: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, ! 5018: 0, aFunc[i].xFunc, 0, 0); ! 5019: } ! 5020: if( rc==SQLITE_OK ){ ! 5021: rc = sqlite3_create_window_function(db, "decimal_sum", 1, ! 5022: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, ! 5023: decimalSumStep, decimalSumFinalize, ! 5024: decimalSumValue, decimalSumInverse, 0); ! 5025: } ! 5026: if( rc==SQLITE_OK ){ ! 5027: rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8, ! 5028: 0, decimalCollFunc); ! 5029: } ! 5030: return rc; ! 5031: } ! 5032: ! 5033: /************************* End ../ext/misc/decimal.c ********************/ ! 5034: /************************* Begin ../ext/misc/ieee754.c ******************/ ! 5035: /* ! 5036: ** 2013-04-17 ! 5037: ** ! 5038: ** The author disclaims copyright to this source code. In place of ! 5039: ** a legal notice, here is a blessing: ! 5040: ** ! 5041: ** May you do good and not evil. ! 5042: ** May you find forgiveness for yourself and forgive others. ! 5043: ** May you share freely, never taking more than you give. ! 5044: ** ! 5045: ****************************************************************************** ! 5046: ** ! 5047: ** This SQLite extension implements functions for the exact display ! 5048: ** and input of IEEE754 Binary64 floating-point numbers. ! 5049: ** ! 5050: ** ieee754(X) ! 5051: ** ieee754(Y,Z) ! 5052: ** ! 5053: ** In the first form, the value X should be a floating-point number. ! 5054: ** The function will return a string of the form 'ieee754(Y,Z)' where ! 5055: ** Y and Z are integers such that X==Y*pow(2,Z). ! 5056: ** ! 5057: ** In the second form, Y and Z are integers which are the mantissa and ! 5058: ** base-2 exponent of a new floating point number. The function returns ! 5059: ** a floating-point value equal to Y*pow(2,Z). ! 5060: ** ! 5061: ** Examples: ! 5062: ** ! 5063: ** ieee754(2.0) -> 'ieee754(2,0)' ! 5064: ** ieee754(45.25) -> 'ieee754(181,-2)' ! 5065: ** ieee754(2, 0) -> 2.0 ! 5066: ** ieee754(181, -2) -> 45.25 ! 5067: ** ! 5068: ** Two additional functions break apart the one-argument ieee754() ! 5069: ** result into separate integer values: ! 5070: ** ! 5071: ** ieee754_mantissa(45.25) -> 181 ! 5072: ** ieee754_exponent(45.25) -> -2 ! 5073: ** ! 5074: ** These functions convert binary64 numbers into blobs and back again. ! 5075: ** ! 5076: ** ieee754_from_blob(x'3ff0000000000000') -> 1.0 ! 5077: ** ieee754_to_blob(1.0) -> x'3ff0000000000000' ! 5078: ** ! 5079: ** In all single-argument functions, if the argument is an 8-byte blob ! 5080: ** then that blob is interpreted as a big-endian binary64 value. ! 5081: ** ! 5082: ** ! 5083: ** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES ! 5084: ** ----------------------------------------------- ! 5085: ** ! 5086: ** This extension in combination with the separate 'decimal' extension ! 5087: ** can be used to compute the exact decimal representation of binary64 ! 5088: ** values. To begin, first compute a table of exponent values: ! 5089: ** ! 5090: ** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT); ! 5091: ** WITH RECURSIVE c(x,v) AS ( ! 5092: ** VALUES(0,'1') ! 5093: ** UNION ALL ! 5094: ** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971 ! 5095: ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; ! 5096: ** WITH RECURSIVE c(x,v) AS ( ! 5097: ** VALUES(-1,'0.5') ! 5098: ** UNION ALL ! 5099: ** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075 ! 5100: ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c; ! 5101: ** ! 5102: ** Then, to compute the exact decimal representation of a floating ! 5103: ** point value (the value 47.49 is used in the example) do: ! 5104: ** ! 5105: ** WITH c(n) AS (VALUES(47.49)) ! 5106: ** ---------------^^^^^---- Replace with whatever you want ! 5107: ** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v) ! 5108: ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n); ! 5109: ** ! 5110: ** Here is a query to show various boundry values for the binary64 ! 5111: ** number format: ! 5112: ** ! 5113: ** WITH c(name,bin) AS (VALUES ! 5114: ** ('minimum positive value', x'0000000000000001'), ! 5115: ** ('maximum subnormal value', x'000fffffffffffff'), ! 5116: ** ('mininum positive nornal value', x'0010000000000000'), ! 5117: ** ('maximum value', x'7fefffffffffffff')) ! 5118: ** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v) ! 5119: ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin); ! 5120: ** ! 5121: */ ! 5122: /* #include "sqlite3ext.h" */ ! 5123: SQLITE_EXTENSION_INIT1 ! 5124: #include <assert.h> ! 5125: #include <string.h> ! 5126: ! 5127: /* Mark a function parameter as unused, to suppress nuisance compiler ! 5128: ** warnings. */ ! 5129: #ifndef UNUSED_PARAMETER ! 5130: # define UNUSED_PARAMETER(X) (void)(X) ! 5131: #endif ! 5132: ! 5133: /* ! 5134: ** Implementation of the ieee754() function ! 5135: */ ! 5136: static void ieee754func( ! 5137: sqlite3_context *context, ! 5138: int argc, ! 5139: sqlite3_value **argv ! 5140: ){ ! 5141: if( argc==1 ){ ! 5142: sqlite3_int64 m, a; ! 5143: double r; ! 5144: int e; ! 5145: int isNeg; ! 5146: char zResult[100]; ! 5147: assert( sizeof(m)==sizeof(r) ); ! 5148: if( sqlite3_value_type(argv[0])==SQLITE_BLOB ! 5149: && sqlite3_value_bytes(argv[0])==sizeof(r) ! 5150: ){ ! 5151: const unsigned char *x = sqlite3_value_blob(argv[0]); ! 5152: unsigned int i; ! 5153: sqlite3_uint64 v = 0; ! 5154: for(i=0; i<sizeof(r); i++){ ! 5155: v = (v<<8) | x[i]; ! 5156: } ! 5157: memcpy(&r, &v, sizeof(r)); ! 5158: }else{ ! 5159: r = sqlite3_value_double(argv[0]); ! 5160: } ! 5161: if( r<0.0 ){ ! 5162: isNeg = 1; ! 5163: r = -r; ! 5164: }else{ ! 5165: isNeg = 0; ! 5166: } ! 5167: memcpy(&a,&r,sizeof(a)); ! 5168: if( a==0 ){ ! 5169: e = 0; ! 5170: m = 0; ! 5171: }else{ ! 5172: e = a>>52; ! 5173: m = a & ((((sqlite3_int64)1)<<52)-1); ! 5174: if( e==0 ){ ! 5175: m <<= 1; ! 5176: }else{ ! 5177: m |= ((sqlite3_int64)1)<<52; ! 5178: } ! 5179: while( e<1075 && m>0 && (m&1)==0 ){ ! 5180: m >>= 1; ! 5181: e++; ! 5182: } ! 5183: if( isNeg ) m = -m; ! 5184: } ! 5185: switch( *(int*)sqlite3_user_data(context) ){ ! 5186: case 0: ! 5187: sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)", ! 5188: m, e-1075); ! 5189: sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); ! 5190: break; ! 5191: case 1: ! 5192: sqlite3_result_int64(context, m); ! 5193: break; ! 5194: case 2: ! 5195: sqlite3_result_int(context, e-1075); ! 5196: break; ! 5197: } ! 5198: }else{ ! 5199: sqlite3_int64 m, e, a; ! 5200: double r; ! 5201: int isNeg = 0; ! 5202: m = sqlite3_value_int64(argv[0]); ! 5203: e = sqlite3_value_int64(argv[1]); ! 5204: if( m<0 ){ ! 5205: isNeg = 1; ! 5206: m = -m; ! 5207: if( m<0 ) return; ! 5208: }else if( m==0 && e>-1000 && e<1000 ){ ! 5209: sqlite3_result_double(context, 0.0); ! 5210: return; ! 5211: } ! 5212: while( (m>>32)&0xffe00000 ){ ! 5213: m >>= 1; ! 5214: e++; ! 5215: } ! 5216: while( m!=0 && ((m>>32)&0xfff00000)==0 ){ ! 5217: m <<= 1; ! 5218: e--; ! 5219: } ! 5220: e += 1075; ! 5221: if( e<=0 ){ ! 5222: /* Subnormal */ ! 5223: m >>= 1-e; ! 5224: e = 0; ! 5225: }else if( e>0x7ff ){ ! 5226: e = 0x7ff; ! 5227: } ! 5228: a = m & ((((sqlite3_int64)1)<<52)-1); ! 5229: a |= e<<52; ! 5230: if( isNeg ) a |= ((sqlite3_uint64)1)<<63; ! 5231: memcpy(&r, &a, sizeof(r)); ! 5232: sqlite3_result_double(context, r); ! 5233: } ! 5234: } ! 5235: ! 5236: /* ! 5237: ** Functions to convert between blobs and floats. ! 5238: */ ! 5239: static void ieee754func_from_blob( ! 5240: sqlite3_context *context, ! 5241: int argc, ! 5242: sqlite3_value **argv ! 5243: ){ ! 5244: UNUSED_PARAMETER(argc); ! 5245: if( sqlite3_value_type(argv[0])==SQLITE_BLOB ! 5246: && sqlite3_value_bytes(argv[0])==sizeof(double) ! 5247: ){ ! 5248: double r; ! 5249: const unsigned char *x = sqlite3_value_blob(argv[0]); ! 5250: unsigned int i; ! 5251: sqlite3_uint64 v = 0; ! 5252: for(i=0; i<sizeof(r); i++){ ! 5253: v = (v<<8) | x[i]; ! 5254: } ! 5255: memcpy(&r, &v, sizeof(r)); ! 5256: sqlite3_result_double(context, r); ! 5257: } ! 5258: } ! 5259: static void ieee754func_to_blob( ! 5260: sqlite3_context *context, ! 5261: int argc, ! 5262: sqlite3_value **argv ! 5263: ){ ! 5264: UNUSED_PARAMETER(argc); ! 5265: if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ! 5266: || sqlite3_value_type(argv[0])==SQLITE_INTEGER ! 5267: ){ ! 5268: double r = sqlite3_value_double(argv[0]); ! 5269: sqlite3_uint64 v; ! 5270: unsigned char a[sizeof(r)]; ! 5271: unsigned int i; ! 5272: memcpy(&v, &r, sizeof(r)); ! 5273: for(i=1; i<=sizeof(r); i++){ ! 5274: a[sizeof(r)-i] = v&0xff; ! 5275: v >>= 8; ! 5276: } ! 5277: sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT); ! 5278: } ! 5279: } ! 5280: ! 5281: ! 5282: #ifdef _WIN32 ! 5283: ! 5284: #endif ! 5285: int sqlite3_ieee_init( ! 5286: sqlite3 *db, ! 5287: char **pzErrMsg, ! 5288: const sqlite3_api_routines *pApi ! 5289: ){ ! 5290: static const struct { ! 5291: char *zFName; ! 5292: int nArg; ! 5293: int iAux; ! 5294: void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ! 5295: } aFunc[] = { ! 5296: { "ieee754", 1, 0, ieee754func }, ! 5297: { "ieee754", 2, 0, ieee754func }, ! 5298: { "ieee754_mantissa", 1, 1, ieee754func }, ! 5299: { "ieee754_exponent", 1, 2, ieee754func }, ! 5300: { "ieee754_to_blob", 1, 0, ieee754func_to_blob }, ! 5301: { "ieee754_from_blob", 1, 0, ieee754func_from_blob }, ! 5302: ! 5303: }; ! 5304: unsigned int i; ! 5305: int rc = SQLITE_OK; ! 5306: SQLITE_EXTENSION_INIT2(pApi); ! 5307: (void)pzErrMsg; /* Unused parameter */ ! 5308: for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ! 5309: rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg, ! 5310: SQLITE_UTF8|SQLITE_INNOCUOUS, ! 5311: (void*)&aFunc[i].iAux, ! 5312: aFunc[i].xFunc, 0, 0); ! 5313: } ! 5314: return rc; ! 5315: } ! 5316: ! 5317: /************************* End ../ext/misc/ieee754.c ********************/ ! 5318: #ifdef SQLITE_HAVE_ZLIB ! 5319: /************************* Begin ../ext/misc/zipfile.c ******************/ ! 5320: /* ! 5321: ** 2017-12-26 ! 5322: ** ! 5323: ** The author disclaims copyright to this source code. In place of ! 5324: ** a legal notice, here is a blessing: ! 5325: ** ! 5326: ** May you do good and not evil. ! 5327: ** May you find forgiveness for yourself and forgive others. ! 5328: ** May you share freely, never taking more than you give. ! 5329: ** ! 5330: ****************************************************************************** ! 5331: ** ! 5332: ** This file implements a virtual table for reading and writing ZIP archive ! 5333: ** files. ! 5334: ** ! 5335: ** Usage example: ! 5336: ** ! 5337: ** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename); ! 5338: ** ! 5339: ** Current limitations: ! 5340: ** ! 5341: ** * No support for encryption ! 5342: ** * No support for ZIP archives spanning multiple files ! 5343: ** * No support for zip64 extensions ! 5344: ** * Only the "inflate/deflate" (zlib) compression method is supported ! 5345: */ ! 5346: /* #include "sqlite3ext.h" */ ! 5347: SQLITE_EXTENSION_INIT1 ! 5348: #include <stdio.h> ! 5349: #include <string.h> ! 5350: #include <assert.h> ! 5351: ! 5352: #include <zlib.h> ! 5353: ! 5354: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 5355: ! 5356: #ifndef SQLITE_AMALGAMATION ! 5357: ! 5358: /* typedef sqlite3_int64 i64; */ ! 5359: /* typedef unsigned char u8; */ ! 5360: typedef unsigned short u16; ! 5361: typedef unsigned long u32; ! 5362: #define MIN(a,b) ((a)<(b) ? (a) : (b)) ! 5363: ! 5364: #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) ! 5365: # define ALWAYS(X) (1) ! 5366: # define NEVER(X) (0) ! 5367: #elif !defined(NDEBUG) ! 5368: # define ALWAYS(X) ((X)?1:(assert(0),0)) ! 5369: # define NEVER(X) ((X)?(assert(0),1):0) ! 5370: #else ! 5371: # define ALWAYS(X) (X) ! 5372: # define NEVER(X) (X) ! 5373: #endif ! 5374: ! 5375: #endif /* SQLITE_AMALGAMATION */ ! 5376: ! 5377: /* ! 5378: ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK. ! 5379: ** ! 5380: ** In some ways it would be better to obtain these values from system ! 5381: ** header files. But, the dependency is undesirable and (a) these ! 5382: ** have been stable for decades, (b) the values are part of POSIX and ! 5383: ** are also made explicit in [man stat], and (c) are part of the ! 5384: ** file format for zip archives. ! 5385: */ ! 5386: #ifndef S_IFDIR ! 5387: # define S_IFDIR 0040000 ! 5388: #endif ! 5389: #ifndef S_IFREG ! 5390: # define S_IFREG 0100000 ! 5391: #endif ! 5392: #ifndef S_IFLNK ! 5393: # define S_IFLNK 0120000 ! 5394: #endif ! 5395: ! 5396: static const char ZIPFILE_SCHEMA[] = ! 5397: "CREATE TABLE y(" ! 5398: "name PRIMARY KEY," /* 0: Name of file in zip archive */ ! 5399: "mode," /* 1: POSIX mode for file */ ! 5400: "mtime," /* 2: Last modification time (secs since 1970)*/ ! 5401: "sz," /* 3: Size of object */ ! 5402: "rawdata," /* 4: Raw data */ ! 5403: "data," /* 5: Uncompressed data */ ! 5404: "method," /* 6: Compression method (integer) */ ! 5405: "z HIDDEN" /* 7: Name of zip file */ ! 5406: ") WITHOUT ROWID;"; ! 5407: ! 5408: #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */ ! 5409: #define ZIPFILE_BUFFER_SIZE (64*1024) ! 5410: ! 5411: ! 5412: /* ! 5413: ** Magic numbers used to read and write zip files. ! 5414: ** ! 5415: ** ZIPFILE_NEWENTRY_MADEBY: ! 5416: ** Use this value for the "version-made-by" field in new zip file ! 5417: ** entries. The upper byte indicates "unix", and the lower byte ! 5418: ** indicates that the zip file matches pkzip specification 3.0. ! 5419: ** This is what info-zip seems to do. ! 5420: ** ! 5421: ** ZIPFILE_NEWENTRY_REQUIRED: ! 5422: ** Value for "version-required-to-extract" field of new entries. ! 5423: ** Version 2.0 is required to support folders and deflate compression. ! 5424: ** ! 5425: ** ZIPFILE_NEWENTRY_FLAGS: ! 5426: ** Value for "general-purpose-bit-flags" field of new entries. Bit ! 5427: ** 11 means "utf-8 filename and comment". ! 5428: ** ! 5429: ** ZIPFILE_SIGNATURE_CDS: ! 5430: ** First 4 bytes of a valid CDS record. ! 5431: ** ! 5432: ** ZIPFILE_SIGNATURE_LFH: ! 5433: ** First 4 bytes of a valid LFH record. ! 5434: ** ! 5435: ** ZIPFILE_SIGNATURE_EOCD ! 5436: ** First 4 bytes of a valid EOCD record. ! 5437: */ ! 5438: #define ZIPFILE_EXTRA_TIMESTAMP 0x5455 ! 5439: #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30) ! 5440: #define ZIPFILE_NEWENTRY_REQUIRED 20 ! 5441: #define ZIPFILE_NEWENTRY_FLAGS 0x800 ! 5442: #define ZIPFILE_SIGNATURE_CDS 0x02014b50 ! 5443: #define ZIPFILE_SIGNATURE_LFH 0x04034b50 ! 5444: #define ZIPFILE_SIGNATURE_EOCD 0x06054b50 ! 5445: ! 5446: /* ! 5447: ** The sizes of the fixed-size part of each of the three main data ! 5448: ** structures in a zip archive. ! 5449: */ ! 5450: #define ZIPFILE_LFH_FIXED_SZ 30 ! 5451: #define ZIPFILE_EOCD_FIXED_SZ 22 ! 5452: #define ZIPFILE_CDS_FIXED_SZ 46 ! 5453: ! 5454: /* ! 5455: *** 4.3.16 End of central directory record: ! 5456: *** ! 5457: *** end of central dir signature 4 bytes (0x06054b50) ! 5458: *** number of this disk 2 bytes ! 5459: *** number of the disk with the ! 5460: *** start of the central directory 2 bytes ! 5461: *** total number of entries in the ! 5462: *** central directory on this disk 2 bytes ! 5463: *** total number of entries in ! 5464: *** the central directory 2 bytes ! 5465: *** size of the central directory 4 bytes ! 5466: *** offset of start of central ! 5467: *** directory with respect to ! 5468: *** the starting disk number 4 bytes ! 5469: *** .ZIP file comment length 2 bytes ! 5470: *** .ZIP file comment (variable size) ! 5471: */ ! 5472: typedef struct ZipfileEOCD ZipfileEOCD; ! 5473: struct ZipfileEOCD { ! 5474: u16 iDisk; ! 5475: u16 iFirstDisk; ! 5476: u16 nEntry; ! 5477: u16 nEntryTotal; ! 5478: u32 nSize; ! 5479: u32 iOffset; ! 5480: }; ! 5481: ! 5482: /* ! 5483: *** 4.3.12 Central directory structure: ! 5484: *** ! 5485: *** ... ! 5486: *** ! 5487: *** central file header signature 4 bytes (0x02014b50) ! 5488: *** version made by 2 bytes ! 5489: *** version needed to extract 2 bytes ! 5490: *** general purpose bit flag 2 bytes ! 5491: *** compression method 2 bytes ! 5492: *** last mod file time 2 bytes ! 5493: *** last mod file date 2 bytes ! 5494: *** crc-32 4 bytes ! 5495: *** compressed size 4 bytes ! 5496: *** uncompressed size 4 bytes ! 5497: *** file name length 2 bytes ! 5498: *** extra field length 2 bytes ! 5499: *** file comment length 2 bytes ! 5500: *** disk number start 2 bytes ! 5501: *** internal file attributes 2 bytes ! 5502: *** external file attributes 4 bytes ! 5503: *** relative offset of local header 4 bytes ! 5504: */ ! 5505: typedef struct ZipfileCDS ZipfileCDS; ! 5506: struct ZipfileCDS { ! 5507: u16 iVersionMadeBy; ! 5508: u16 iVersionExtract; ! 5509: u16 flags; ! 5510: u16 iCompression; ! 5511: u16 mTime; ! 5512: u16 mDate; ! 5513: u32 crc32; ! 5514: u32 szCompressed; ! 5515: u32 szUncompressed; ! 5516: u16 nFile; ! 5517: u16 nExtra; ! 5518: u16 nComment; ! 5519: u16 iDiskStart; ! 5520: u16 iInternalAttr; ! 5521: u32 iExternalAttr; ! 5522: u32 iOffset; ! 5523: char *zFile; /* Filename (sqlite3_malloc()) */ ! 5524: }; ! 5525: ! 5526: /* ! 5527: *** 4.3.7 Local file header: ! 5528: *** ! 5529: *** local file header signature 4 bytes (0x04034b50) ! 5530: *** version needed to extract 2 bytes ! 5531: *** general purpose bit flag 2 bytes ! 5532: *** compression method 2 bytes ! 5533: *** last mod file time 2 bytes ! 5534: *** last mod file date 2 bytes ! 5535: *** crc-32 4 bytes ! 5536: *** compressed size 4 bytes ! 5537: *** uncompressed size 4 bytes ! 5538: *** file name length 2 bytes ! 5539: *** extra field length 2 bytes ! 5540: *** ! 5541: */ ! 5542: typedef struct ZipfileLFH ZipfileLFH; ! 5543: struct ZipfileLFH { ! 5544: u16 iVersionExtract; ! 5545: u16 flags; ! 5546: u16 iCompression; ! 5547: u16 mTime; ! 5548: u16 mDate; ! 5549: u32 crc32; ! 5550: u32 szCompressed; ! 5551: u32 szUncompressed; ! 5552: u16 nFile; ! 5553: u16 nExtra; ! 5554: }; ! 5555: ! 5556: typedef struct ZipfileEntry ZipfileEntry; ! 5557: struct ZipfileEntry { ! 5558: ZipfileCDS cds; /* Parsed CDS record */ ! 5559: u32 mUnixTime; /* Modification time, in UNIX format */ ! 5560: u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */ ! 5561: i64 iDataOff; /* Offset to data in file (if aData==0) */ ! 5562: u8 *aData; /* cds.szCompressed bytes of compressed data */ ! 5563: ZipfileEntry *pNext; /* Next element in in-memory CDS */ ! 5564: }; ! 5565: ! 5566: /* ! 5567: ** Cursor type for zipfile tables. ! 5568: */ ! 5569: typedef struct ZipfileCsr ZipfileCsr; ! 5570: struct ZipfileCsr { ! 5571: sqlite3_vtab_cursor base; /* Base class - must be first */ ! 5572: i64 iId; /* Cursor ID */ ! 5573: u8 bEof; /* True when at EOF */ ! 5574: u8 bNoop; /* If next xNext() call is no-op */ ! 5575: ! 5576: /* Used outside of write transactions */ ! 5577: FILE *pFile; /* Zip file */ ! 5578: i64 iNextOff; /* Offset of next record in central directory */ ! 5579: ZipfileEOCD eocd; /* Parse of central directory record */ ! 5580: ! 5581: ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */ ! 5582: ZipfileEntry *pCurrent; /* Current entry */ ! 5583: ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */ ! 5584: }; ! 5585: ! 5586: typedef struct ZipfileTab ZipfileTab; ! 5587: struct ZipfileTab { ! 5588: sqlite3_vtab base; /* Base class - must be first */ ! 5589: char *zFile; /* Zip file this table accesses (may be NULL) */ ! 5590: sqlite3 *db; /* Host database connection */ ! 5591: u8 *aBuffer; /* Temporary buffer used for various tasks */ ! 5592: ! 5593: ZipfileCsr *pCsrList; /* List of cursors */ ! 5594: i64 iNextCsrid; ! 5595: ! 5596: /* The following are used by write transactions only */ ! 5597: ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */ ! 5598: ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */ ! 5599: FILE *pWriteFd; /* File handle open on zip archive */ ! 5600: i64 szCurrent; /* Current size of zip archive */ ! 5601: i64 szOrig; /* Size of archive at start of transaction */ ! 5602: }; ! 5603: ! 5604: /* ! 5605: ** Set the error message contained in context ctx to the results of ! 5606: ** vprintf(zFmt, ...). ! 5607: */ ! 5608: static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ! 5609: char *zMsg = 0; ! 5610: va_list ap; ! 5611: va_start(ap, zFmt); ! 5612: zMsg = sqlite3_vmprintf(zFmt, ap); ! 5613: sqlite3_result_error(ctx, zMsg, -1); ! 5614: sqlite3_free(zMsg); ! 5615: va_end(ap); ! 5616: } ! 5617: ! 5618: /* ! 5619: ** If string zIn is quoted, dequote it in place. Otherwise, if the string ! 5620: ** is not quoted, do nothing. ! 5621: */ ! 5622: static void zipfileDequote(char *zIn){ ! 5623: char q = zIn[0]; ! 5624: if( q=='"' || q=='\'' || q=='`' || q=='[' ){ ! 5625: int iIn = 1; ! 5626: int iOut = 0; ! 5627: if( q=='[' ) q = ']'; ! 5628: while( ALWAYS(zIn[iIn]) ){ ! 5629: char c = zIn[iIn++]; ! 5630: if( c==q && zIn[iIn++]!=q ) break; ! 5631: zIn[iOut++] = c; ! 5632: } ! 5633: zIn[iOut] = '\0'; ! 5634: } ! 5635: } ! 5636: ! 5637: /* ! 5638: ** Construct a new ZipfileTab virtual table object. ! 5639: ** ! 5640: ** argv[0] -> module name ("zipfile") ! 5641: ** argv[1] -> database name ! 5642: ** argv[2] -> table name ! 5643: ** argv[...] -> "column name" and other module argument fields. ! 5644: */ ! 5645: static int zipfileConnect( ! 5646: sqlite3 *db, ! 5647: void *pAux, ! 5648: int argc, const char *const*argv, ! 5649: sqlite3_vtab **ppVtab, ! 5650: char **pzErr ! 5651: ){ ! 5652: int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE; ! 5653: int nFile = 0; ! 5654: const char *zFile = 0; ! 5655: ZipfileTab *pNew = 0; ! 5656: int rc; ! 5657: ! 5658: /* If the table name is not "zipfile", require that the argument be ! 5659: ** specified. This stops zipfile tables from being created as: ! 5660: ** ! 5661: ** CREATE VIRTUAL TABLE zzz USING zipfile(); ! 5662: ** ! 5663: ** It does not prevent: ! 5664: ** ! 5665: ** CREATE VIRTUAL TABLE zipfile USING zipfile(); ! 5666: */ ! 5667: assert( 0==sqlite3_stricmp(argv[0], "zipfile") ); ! 5668: if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){ ! 5669: *pzErr = sqlite3_mprintf("zipfile constructor requires one argument"); ! 5670: return SQLITE_ERROR; ! 5671: } ! 5672: ! 5673: if( argc>3 ){ ! 5674: zFile = argv[3]; ! 5675: nFile = (int)strlen(zFile)+1; ! 5676: } ! 5677: ! 5678: rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); ! 5679: if( rc==SQLITE_OK ){ ! 5680: pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); ! 5681: if( pNew==0 ) return SQLITE_NOMEM; ! 5682: memset(pNew, 0, nByte+nFile); ! 5683: pNew->db = db; ! 5684: pNew->aBuffer = (u8*)&pNew[1]; ! 5685: if( zFile ){ ! 5686: pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; ! 5687: memcpy(pNew->zFile, zFile, nFile); ! 5688: zipfileDequote(pNew->zFile); ! 5689: } ! 5690: } ! 5691: sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); ! 5692: *ppVtab = (sqlite3_vtab*)pNew; ! 5693: return rc; ! 5694: } ! 5695: ! 5696: /* ! 5697: ** Free the ZipfileEntry structure indicated by the only argument. ! 5698: */ ! 5699: static void zipfileEntryFree(ZipfileEntry *p){ ! 5700: if( p ){ ! 5701: sqlite3_free(p->cds.zFile); ! 5702: sqlite3_free(p); ! 5703: } ! 5704: } ! 5705: ! 5706: /* ! 5707: ** Release resources that should be freed at the end of a write ! 5708: ** transaction. ! 5709: */ ! 5710: static void zipfileCleanupTransaction(ZipfileTab *pTab){ ! 5711: ZipfileEntry *pEntry; ! 5712: ZipfileEntry *pNext; ! 5713: ! 5714: if( pTab->pWriteFd ){ ! 5715: fclose(pTab->pWriteFd); ! 5716: pTab->pWriteFd = 0; ! 5717: } ! 5718: for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){ ! 5719: pNext = pEntry->pNext; ! 5720: zipfileEntryFree(pEntry); ! 5721: } ! 5722: pTab->pFirstEntry = 0; ! 5723: pTab->pLastEntry = 0; ! 5724: pTab->szCurrent = 0; ! 5725: pTab->szOrig = 0; ! 5726: } ! 5727: ! 5728: /* ! 5729: ** This method is the destructor for zipfile vtab objects. ! 5730: */ ! 5731: static int zipfileDisconnect(sqlite3_vtab *pVtab){ ! 5732: zipfileCleanupTransaction((ZipfileTab*)pVtab); ! 5733: sqlite3_free(pVtab); ! 5734: return SQLITE_OK; ! 5735: } ! 5736: ! 5737: /* ! 5738: ** Constructor for a new ZipfileCsr object. ! 5739: */ ! 5740: static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ ! 5741: ZipfileTab *pTab = (ZipfileTab*)p; ! 5742: ZipfileCsr *pCsr; ! 5743: pCsr = sqlite3_malloc(sizeof(*pCsr)); ! 5744: *ppCsr = (sqlite3_vtab_cursor*)pCsr; ! 5745: if( pCsr==0 ){ ! 5746: return SQLITE_NOMEM; ! 5747: } ! 5748: memset(pCsr, 0, sizeof(*pCsr)); ! 5749: pCsr->iId = ++pTab->iNextCsrid; ! 5750: pCsr->pCsrNext = pTab->pCsrList; ! 5751: pTab->pCsrList = pCsr; ! 5752: return SQLITE_OK; ! 5753: } ! 5754: ! 5755: /* ! 5756: ** Reset a cursor back to the state it was in when first returned ! 5757: ** by zipfileOpen(). ! 5758: */ ! 5759: static void zipfileResetCursor(ZipfileCsr *pCsr){ ! 5760: ZipfileEntry *p; ! 5761: ZipfileEntry *pNext; ! 5762: ! 5763: pCsr->bEof = 0; ! 5764: if( pCsr->pFile ){ ! 5765: fclose(pCsr->pFile); ! 5766: pCsr->pFile = 0; ! 5767: zipfileEntryFree(pCsr->pCurrent); ! 5768: pCsr->pCurrent = 0; ! 5769: } ! 5770: ! 5771: for(p=pCsr->pFreeEntry; p; p=pNext){ ! 5772: pNext = p->pNext; ! 5773: zipfileEntryFree(p); ! 5774: } ! 5775: } ! 5776: ! 5777: /* ! 5778: ** Destructor for an ZipfileCsr. ! 5779: */ ! 5780: static int zipfileClose(sqlite3_vtab_cursor *cur){ ! 5781: ZipfileCsr *pCsr = (ZipfileCsr*)cur; ! 5782: ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab); ! 5783: ZipfileCsr **pp; ! 5784: zipfileResetCursor(pCsr); ! 5785: ! 5786: /* Remove this cursor from the ZipfileTab.pCsrList list. */ ! 5787: for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext)); ! 5788: *pp = pCsr->pCsrNext; ! 5789: ! 5790: sqlite3_free(pCsr); ! 5791: return SQLITE_OK; ! 5792: } ! 5793: ! 5794: /* ! 5795: ** Set the error message for the virtual table associated with cursor ! 5796: ** pCsr to the results of vprintf(zFmt, ...). ! 5797: */ ! 5798: static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){ ! 5799: va_list ap; ! 5800: va_start(ap, zFmt); ! 5801: sqlite3_free(pTab->base.zErrMsg); ! 5802: pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap); ! 5803: va_end(ap); ! 5804: } ! 5805: static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ ! 5806: va_list ap; ! 5807: va_start(ap, zFmt); ! 5808: sqlite3_free(pCsr->base.pVtab->zErrMsg); ! 5809: pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); ! 5810: va_end(ap); ! 5811: } ! 5812: ! 5813: /* ! 5814: ** Read nRead bytes of data from offset iOff of file pFile into buffer ! 5815: ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code ! 5816: ** otherwise. ! 5817: ** ! 5818: ** If an error does occur, output variable (*pzErrmsg) may be set to point ! 5819: ** to an English language error message. It is the responsibility of the ! 5820: ** caller to eventually free this buffer using ! 5821: ** sqlite3_free(). ! 5822: */ ! 5823: static int zipfileReadData( ! 5824: FILE *pFile, /* Read from this file */ ! 5825: u8 *aRead, /* Read into this buffer */ ! 5826: int nRead, /* Number of bytes to read */ ! 5827: i64 iOff, /* Offset to read from */ ! 5828: char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ ! 5829: ){ ! 5830: size_t n; ! 5831: fseek(pFile, (long)iOff, SEEK_SET); ! 5832: n = fread(aRead, 1, nRead, pFile); ! 5833: if( (int)n!=nRead ){ ! 5834: *pzErrmsg = sqlite3_mprintf("error in fread()"); ! 5835: return SQLITE_ERROR; ! 5836: } ! 5837: return SQLITE_OK; ! 5838: } ! 5839: ! 5840: static int zipfileAppendData( ! 5841: ZipfileTab *pTab, ! 5842: const u8 *aWrite, ! 5843: int nWrite ! 5844: ){ ! 5845: size_t n; ! 5846: fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); ! 5847: n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); ! 5848: if( (int)n!=nWrite ){ ! 5849: pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); ! 5850: return SQLITE_ERROR; ! 5851: } ! 5852: pTab->szCurrent += nWrite; ! 5853: return SQLITE_OK; ! 5854: } ! 5855: ! 5856: /* ! 5857: ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf. ! 5858: */ ! 5859: static u16 zipfileGetU16(const u8 *aBuf){ ! 5860: return (aBuf[1] << 8) + aBuf[0]; ! 5861: } ! 5862: ! 5863: /* ! 5864: ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf. ! 5865: */ ! 5866: static u32 zipfileGetU32(const u8 *aBuf){ ! 5867: return ((u32)(aBuf[3]) << 24) ! 5868: + ((u32)(aBuf[2]) << 16) ! 5869: + ((u32)(aBuf[1]) << 8) ! 5870: + ((u32)(aBuf[0]) << 0); ! 5871: } ! 5872: ! 5873: /* ! 5874: ** Write a 16-bit little endiate integer into buffer aBuf. ! 5875: */ ! 5876: static void zipfilePutU16(u8 *aBuf, u16 val){ ! 5877: aBuf[0] = val & 0xFF; ! 5878: aBuf[1] = (val>>8) & 0xFF; ! 5879: } ! 5880: ! 5881: /* ! 5882: ** Write a 32-bit little endiate integer into buffer aBuf. ! 5883: */ ! 5884: static void zipfilePutU32(u8 *aBuf, u32 val){ ! 5885: aBuf[0] = val & 0xFF; ! 5886: aBuf[1] = (val>>8) & 0xFF; ! 5887: aBuf[2] = (val>>16) & 0xFF; ! 5888: aBuf[3] = (val>>24) & 0xFF; ! 5889: } ! 5890: ! 5891: #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) ) ! 5892: #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) ) ! 5893: ! 5894: #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; } ! 5895: #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; } ! 5896: ! 5897: /* ! 5898: ** Magic numbers used to read CDS records. ! 5899: */ ! 5900: #define ZIPFILE_CDS_NFILE_OFF 28 ! 5901: #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20 ! 5902: ! 5903: /* ! 5904: ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR ! 5905: ** if the record is not well-formed, or SQLITE_OK otherwise. ! 5906: */ ! 5907: static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){ ! 5908: u8 *aRead = aBuf; ! 5909: u32 sig = zipfileRead32(aRead); ! 5910: int rc = SQLITE_OK; ! 5911: if( sig!=ZIPFILE_SIGNATURE_CDS ){ ! 5912: rc = SQLITE_ERROR; ! 5913: }else{ ! 5914: pCDS->iVersionMadeBy = zipfileRead16(aRead); ! 5915: pCDS->iVersionExtract = zipfileRead16(aRead); ! 5916: pCDS->flags = zipfileRead16(aRead); ! 5917: pCDS->iCompression = zipfileRead16(aRead); ! 5918: pCDS->mTime = zipfileRead16(aRead); ! 5919: pCDS->mDate = zipfileRead16(aRead); ! 5920: pCDS->crc32 = zipfileRead32(aRead); ! 5921: pCDS->szCompressed = zipfileRead32(aRead); ! 5922: pCDS->szUncompressed = zipfileRead32(aRead); ! 5923: assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); ! 5924: pCDS->nFile = zipfileRead16(aRead); ! 5925: pCDS->nExtra = zipfileRead16(aRead); ! 5926: pCDS->nComment = zipfileRead16(aRead); ! 5927: pCDS->iDiskStart = zipfileRead16(aRead); ! 5928: pCDS->iInternalAttr = zipfileRead16(aRead); ! 5929: pCDS->iExternalAttr = zipfileRead32(aRead); ! 5930: pCDS->iOffset = zipfileRead32(aRead); ! 5931: assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] ); ! 5932: } ! 5933: ! 5934: return rc; ! 5935: } ! 5936: ! 5937: /* ! 5938: ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR ! 5939: ** if the record is not well-formed, or SQLITE_OK otherwise. ! 5940: */ ! 5941: static int zipfileReadLFH( ! 5942: u8 *aBuffer, ! 5943: ZipfileLFH *pLFH ! 5944: ){ ! 5945: u8 *aRead = aBuffer; ! 5946: int rc = SQLITE_OK; ! 5947: ! 5948: u32 sig = zipfileRead32(aRead); ! 5949: if( sig!=ZIPFILE_SIGNATURE_LFH ){ ! 5950: rc = SQLITE_ERROR; ! 5951: }else{ ! 5952: pLFH->iVersionExtract = zipfileRead16(aRead); ! 5953: pLFH->flags = zipfileRead16(aRead); ! 5954: pLFH->iCompression = zipfileRead16(aRead); ! 5955: pLFH->mTime = zipfileRead16(aRead); ! 5956: pLFH->mDate = zipfileRead16(aRead); ! 5957: pLFH->crc32 = zipfileRead32(aRead); ! 5958: pLFH->szCompressed = zipfileRead32(aRead); ! 5959: pLFH->szUncompressed = zipfileRead32(aRead); ! 5960: pLFH->nFile = zipfileRead16(aRead); ! 5961: pLFH->nExtra = zipfileRead16(aRead); ! 5962: } ! 5963: return rc; ! 5964: } ! 5965: ! 5966: ! 5967: /* ! 5968: ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields. ! 5969: ** Scan through this buffer to find an "extra-timestamp" field. If one ! 5970: ** exists, extract the 32-bit modification-timestamp from it and store ! 5971: ** the value in output parameter *pmTime. ! 5972: ** ! 5973: ** Zero is returned if no extra-timestamp record could be found (and so ! 5974: ** *pmTime is left unchanged), or non-zero otherwise. ! 5975: ** ! 5976: ** The general format of an extra field is: ! 5977: ** ! 5978: ** Header ID 2 bytes ! 5979: ** Data Size 2 bytes ! 5980: ** Data N bytes ! 5981: */ ! 5982: static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){ ! 5983: int ret = 0; ! 5984: u8 *p = aExtra; ! 5985: u8 *pEnd = &aExtra[nExtra]; ! 5986: ! 5987: while( p<pEnd ){ ! 5988: u16 id = zipfileRead16(p); ! 5989: u16 nByte = zipfileRead16(p); ! 5990: ! 5991: switch( id ){ ! 5992: case ZIPFILE_EXTRA_TIMESTAMP: { ! 5993: u8 b = p[0]; ! 5994: if( b & 0x01 ){ /* 0x01 -> modtime is present */ ! 5995: *pmTime = zipfileGetU32(&p[1]); ! 5996: ret = 1; ! 5997: } ! 5998: break; ! 5999: } ! 6000: } ! 6001: ! 6002: p += nByte; ! 6003: } ! 6004: return ret; ! 6005: } ! 6006: ! 6007: /* ! 6008: ** Convert the standard MS-DOS timestamp stored in the mTime and mDate ! 6009: ** fields of the CDS structure passed as the only argument to a 32-bit ! 6010: ** UNIX seconds-since-the-epoch timestamp. Return the result. ! 6011: ** ! 6012: ** "Standard" MS-DOS time format: ! 6013: ** ! 6014: ** File modification time: ! 6015: ** Bits 00-04: seconds divided by 2 ! 6016: ** Bits 05-10: minute ! 6017: ** Bits 11-15: hour ! 6018: ** File modification date: ! 6019: ** Bits 00-04: day ! 6020: ** Bits 05-08: month (1-12) ! 6021: ** Bits 09-15: years from 1980 ! 6022: ** ! 6023: ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx ! 6024: */ ! 6025: static u32 zipfileMtime(ZipfileCDS *pCDS){ ! 6026: int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F)); ! 6027: int M = ((pCDS->mDate >> 5) & 0x0F); ! 6028: int D = (pCDS->mDate & 0x1F); ! 6029: int B = -13; ! 6030: ! 6031: int sec = (pCDS->mTime & 0x1F)*2; ! 6032: int min = (pCDS->mTime >> 5) & 0x3F; ! 6033: int hr = (pCDS->mTime >> 11) & 0x1F; ! 6034: i64 JD; ! 6035: ! 6036: /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */ ! 6037: ! 6038: /* Calculate the JD in seconds for noon on the day in question */ ! 6039: if( M<3 ){ ! 6040: Y = Y-1; ! 6041: M = M+12; ! 6042: } ! 6043: JD = (i64)(24*60*60) * ( ! 6044: (int)(365.25 * (Y + 4716)) ! 6045: + (int)(30.6001 * (M + 1)) ! 6046: + D + B - 1524 ! 6047: ); ! 6048: ! 6049: /* Correct the JD for the time within the day */ ! 6050: JD += (hr-12) * 3600 + min * 60 + sec; ! 6051: ! 6052: /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */ ! 6053: return (u32)(JD - (i64)(24405875) * 24*60*6); ! 6054: } ! 6055: ! 6056: /* ! 6057: ** The opposite of zipfileMtime(). This function populates the mTime and ! 6058: ** mDate fields of the CDS structure passed as the first argument according ! 6059: ** to the UNIX timestamp value passed as the second. ! 6060: */ ! 6061: static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){ ! 6062: /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */ ! 6063: i64 JD = (i64)2440588 + mUnixTime / (24*60*60); ! 6064: ! 6065: int A, B, C, D, E; ! 6066: int yr, mon, day; ! 6067: int hr, min, sec; ! 6068: ! 6069: A = (int)((JD - 1867216.25)/36524.25); ! 6070: A = (int)(JD + 1 + A - (A/4)); ! 6071: B = A + 1524; ! 6072: C = (int)((B - 122.1)/365.25); ! 6073: D = (36525*(C&32767))/100; ! 6074: E = (int)((B-D)/30.6001); ! 6075: ! 6076: day = B - D - (int)(30.6001*E); ! 6077: mon = (E<14 ? E-1 : E-13); ! 6078: yr = mon>2 ? C-4716 : C-4715; ! 6079: ! 6080: hr = (mUnixTime % (24*60*60)) / (60*60); ! 6081: min = (mUnixTime % (60*60)) / 60; ! 6082: sec = (mUnixTime % 60); ! 6083: ! 6084: if( yr>=1980 ){ ! 6085: pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9)); ! 6086: pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11)); ! 6087: }else{ ! 6088: pCds->mDate = pCds->mTime = 0; ! 6089: } ! 6090: ! 6091: assert( mUnixTime<315507600 ! 6092: || mUnixTime==zipfileMtime(pCds) ! 6093: || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) ! 6094: /* || (mUnixTime % 2) */ ! 6095: ); ! 6096: } ! 6097: ! 6098: /* ! 6099: ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in ! 6100: ** size) containing an entire zip archive image. Or, if aBlob is NULL, ! 6101: ** then pFile is a file-handle open on a zip file. In either case, this ! 6102: ** function creates a ZipfileEntry object based on the zip archive entry ! 6103: ** for which the CDS record is at offset iOff. ! 6104: ** ! 6105: ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to ! 6106: ** the new object. Otherwise, an SQLite error code is returned and the ! 6107: ** final value of (*ppEntry) undefined. ! 6108: */ ! 6109: static int zipfileGetEntry( ! 6110: ZipfileTab *pTab, /* Store any error message here */ ! 6111: const u8 *aBlob, /* Pointer to in-memory file image */ ! 6112: int nBlob, /* Size of aBlob[] in bytes */ ! 6113: FILE *pFile, /* If aBlob==0, read from this file */ ! 6114: i64 iOff, /* Offset of CDS record */ ! 6115: ZipfileEntry **ppEntry /* OUT: Pointer to new object */ ! 6116: ){ ! 6117: u8 *aRead; ! 6118: char **pzErr = &pTab->base.zErrMsg; ! 6119: int rc = SQLITE_OK; ! 6120: ! 6121: if( aBlob==0 ){ ! 6122: aRead = pTab->aBuffer; ! 6123: rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr); ! 6124: }else{ ! 6125: aRead = (u8*)&aBlob[iOff]; ! 6126: } ! 6127: ! 6128: if( rc==SQLITE_OK ){ ! 6129: sqlite3_int64 nAlloc; ! 6130: ZipfileEntry *pNew; ! 6131: ! 6132: int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]); ! 6133: int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]); ! 6134: nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]); ! 6135: ! 6136: nAlloc = sizeof(ZipfileEntry) + nExtra; ! 6137: if( aBlob ){ ! 6138: nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]); ! 6139: } ! 6140: ! 6141: pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc); ! 6142: if( pNew==0 ){ ! 6143: rc = SQLITE_NOMEM; ! 6144: }else{ ! 6145: memset(pNew, 0, sizeof(ZipfileEntry)); ! 6146: rc = zipfileReadCDS(aRead, &pNew->cds); ! 6147: if( rc!=SQLITE_OK ){ ! 6148: *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); ! 6149: }else if( aBlob==0 ){ ! 6150: rc = zipfileReadData( ! 6151: pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr ! 6152: ); ! 6153: }else{ ! 6154: aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; ! 6155: } ! 6156: } ! 6157: ! 6158: if( rc==SQLITE_OK ){ ! 6159: u32 *pt = &pNew->mUnixTime; ! 6160: pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); ! 6161: pNew->aExtra = (u8*)&pNew[1]; ! 6162: memcpy(pNew->aExtra, &aRead[nFile], nExtra); ! 6163: if( pNew->cds.zFile==0 ){ ! 6164: rc = SQLITE_NOMEM; ! 6165: }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){ ! 6166: pNew->mUnixTime = zipfileMtime(&pNew->cds); ! 6167: } ! 6168: } ! 6169: ! 6170: if( rc==SQLITE_OK ){ ! 6171: static const int szFix = ZIPFILE_LFH_FIXED_SZ; ! 6172: ZipfileLFH lfh; ! 6173: if( pFile ){ ! 6174: rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); ! 6175: }else{ ! 6176: aRead = (u8*)&aBlob[pNew->cds.iOffset]; ! 6177: } ! 6178: ! 6179: rc = zipfileReadLFH(aRead, &lfh); ! 6180: if( rc==SQLITE_OK ){ ! 6181: pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; ! 6182: pNew->iDataOff += lfh.nFile + lfh.nExtra; ! 6183: if( aBlob && pNew->cds.szCompressed ){ ! 6184: pNew->aData = &pNew->aExtra[nExtra]; ! 6185: memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); ! 6186: } ! 6187: }else{ ! 6188: *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", ! 6189: (int)pNew->cds.iOffset ! 6190: ); ! 6191: } ! 6192: } ! 6193: ! 6194: if( rc!=SQLITE_OK ){ ! 6195: zipfileEntryFree(pNew); ! 6196: }else{ ! 6197: *ppEntry = pNew; ! 6198: } ! 6199: } ! 6200: ! 6201: return rc; ! 6202: } ! 6203: ! 6204: /* ! 6205: ** Advance an ZipfileCsr to its next row of output. ! 6206: */ ! 6207: static int zipfileNext(sqlite3_vtab_cursor *cur){ ! 6208: ZipfileCsr *pCsr = (ZipfileCsr*)cur; ! 6209: int rc = SQLITE_OK; ! 6210: ! 6211: if( pCsr->pFile ){ ! 6212: i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; ! 6213: zipfileEntryFree(pCsr->pCurrent); ! 6214: pCsr->pCurrent = 0; ! 6215: if( pCsr->iNextOff>=iEof ){ ! 6216: pCsr->bEof = 1; ! 6217: }else{ ! 6218: ZipfileEntry *p = 0; ! 6219: ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab); ! 6220: rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p); ! 6221: if( rc==SQLITE_OK ){ ! 6222: pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ; ! 6223: pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment; ! 6224: } ! 6225: pCsr->pCurrent = p; ! 6226: } ! 6227: }else{ ! 6228: if( !pCsr->bNoop ){ ! 6229: pCsr->pCurrent = pCsr->pCurrent->pNext; ! 6230: } ! 6231: if( pCsr->pCurrent==0 ){ ! 6232: pCsr->bEof = 1; ! 6233: } ! 6234: } ! 6235: ! 6236: pCsr->bNoop = 0; ! 6237: return rc; ! 6238: } ! 6239: ! 6240: static void zipfileFree(void *p) { ! 6241: sqlite3_free(p); ! 6242: } ! 6243: ! 6244: /* ! 6245: ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the ! 6246: ** size is nOut bytes. This function uncompresses the data and sets the ! 6247: ** return value in context pCtx to the result (a blob). ! 6248: ** ! 6249: ** If an error occurs, an error code is left in pCtx instead. ! 6250: */ ! 6251: static void zipfileInflate( ! 6252: sqlite3_context *pCtx, /* Store result here */ ! 6253: const u8 *aIn, /* Compressed data */ ! 6254: int nIn, /* Size of buffer aIn[] in bytes */ ! 6255: int nOut /* Expected output size */ ! 6256: ){ ! 6257: u8 *aRes = sqlite3_malloc(nOut); ! 6258: if( aRes==0 ){ ! 6259: sqlite3_result_error_nomem(pCtx); ! 6260: }else{ ! 6261: int err; ! 6262: z_stream str; ! 6263: memset(&str, 0, sizeof(str)); ! 6264: ! 6265: str.next_in = (Byte*)aIn; ! 6266: str.avail_in = nIn; ! 6267: str.next_out = (Byte*)aRes; ! 6268: str.avail_out = nOut; ! 6269: ! 6270: err = inflateInit2(&str, -15); ! 6271: if( err!=Z_OK ){ ! 6272: zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err); ! 6273: }else{ ! 6274: err = inflate(&str, Z_NO_FLUSH); ! 6275: if( err!=Z_STREAM_END ){ ! 6276: zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); ! 6277: }else{ ! 6278: sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree); ! 6279: aRes = 0; ! 6280: } ! 6281: } ! 6282: sqlite3_free(aRes); ! 6283: inflateEnd(&str); ! 6284: } ! 6285: } ! 6286: ! 6287: /* ! 6288: ** Buffer aIn (size nIn bytes) contains uncompressed data. This function ! 6289: ** compresses it and sets (*ppOut) to point to a buffer containing the ! 6290: ** compressed data. The caller is responsible for eventually calling ! 6291: ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) ! 6292: ** is set to the size of buffer (*ppOut) in bytes. ! 6293: ** ! 6294: ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error ! 6295: ** code is returned and an error message left in virtual-table handle ! 6296: ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this ! 6297: ** case. ! 6298: */ ! 6299: static int zipfileDeflate( ! 6300: const u8 *aIn, int nIn, /* Input */ ! 6301: u8 **ppOut, int *pnOut, /* Output */ ! 6302: char **pzErr /* OUT: Error message */ ! 6303: ){ ! 6304: int rc = SQLITE_OK; ! 6305: sqlite3_int64 nAlloc; ! 6306: z_stream str; ! 6307: u8 *aOut; ! 6308: ! 6309: memset(&str, 0, sizeof(str)); ! 6310: str.next_in = (Bytef*)aIn; ! 6311: str.avail_in = nIn; ! 6312: deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); ! 6313: ! 6314: nAlloc = deflateBound(&str, nIn); ! 6315: aOut = (u8*)sqlite3_malloc64(nAlloc); ! 6316: if( aOut==0 ){ ! 6317: rc = SQLITE_NOMEM; ! 6318: }else{ ! 6319: int res; ! 6320: str.next_out = aOut; ! 6321: str.avail_out = nAlloc; ! 6322: res = deflate(&str, Z_FINISH); ! 6323: if( res==Z_STREAM_END ){ ! 6324: *ppOut = aOut; ! 6325: *pnOut = (int)str.total_out; ! 6326: }else{ ! 6327: sqlite3_free(aOut); ! 6328: *pzErr = sqlite3_mprintf("zipfile: deflate() error"); ! 6329: rc = SQLITE_ERROR; ! 6330: } ! 6331: deflateEnd(&str); ! 6332: } ! 6333: ! 6334: return rc; ! 6335: } ! 6336: ! 6337: ! 6338: /* ! 6339: ** Return values of columns for the row at which the series_cursor ! 6340: ** is currently pointing. ! 6341: */ ! 6342: static int zipfileColumn( ! 6343: sqlite3_vtab_cursor *cur, /* The cursor */ ! 6344: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ! 6345: int i /* Which column to return */ ! 6346: ){ ! 6347: ZipfileCsr *pCsr = (ZipfileCsr*)cur; ! 6348: ZipfileCDS *pCDS = &pCsr->pCurrent->cds; ! 6349: int rc = SQLITE_OK; ! 6350: switch( i ){ ! 6351: case 0: /* name */ ! 6352: sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT); ! 6353: break; ! 6354: case 1: /* mode */ ! 6355: /* TODO: Whether or not the following is correct surely depends on ! 6356: ** the platform on which the archive was created. */ ! 6357: sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16); ! 6358: break; ! 6359: case 2: { /* mtime */ ! 6360: sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime); ! 6361: break; ! 6362: } ! 6363: case 3: { /* sz */ ! 6364: if( sqlite3_vtab_nochange(ctx)==0 ){ ! 6365: sqlite3_result_int64(ctx, pCDS->szUncompressed); ! 6366: } ! 6367: break; ! 6368: } ! 6369: case 4: /* rawdata */ ! 6370: if( sqlite3_vtab_nochange(ctx) ) break; ! 6371: case 5: { /* data */ ! 6372: if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){ ! 6373: int sz = pCDS->szCompressed; ! 6374: int szFinal = pCDS->szUncompressed; ! 6375: if( szFinal>0 ){ ! 6376: u8 *aBuf; ! 6377: u8 *aFree = 0; ! 6378: if( pCsr->pCurrent->aData ){ ! 6379: aBuf = pCsr->pCurrent->aData; ! 6380: }else{ ! 6381: aBuf = aFree = sqlite3_malloc64(sz); ! 6382: if( aBuf==0 ){ ! 6383: rc = SQLITE_NOMEM; ! 6384: }else{ ! 6385: FILE *pFile = pCsr->pFile; ! 6386: if( pFile==0 ){ ! 6387: pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd; ! 6388: } ! 6389: rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff, ! 6390: &pCsr->base.pVtab->zErrMsg ! 6391: ); ! 6392: } ! 6393: } ! 6394: if( rc==SQLITE_OK ){ ! 6395: if( i==5 && pCDS->iCompression ){ ! 6396: zipfileInflate(ctx, aBuf, sz, szFinal); ! 6397: }else{ ! 6398: sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT); ! 6399: } ! 6400: } ! 6401: sqlite3_free(aFree); ! 6402: }else{ ! 6403: /* Figure out if this is a directory or a zero-sized file. Consider ! 6404: ** it to be a directory either if the mode suggests so, or if ! 6405: ** the final character in the name is '/'. */ ! 6406: u32 mode = pCDS->iExternalAttr >> 16; ! 6407: if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){ ! 6408: sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC); ! 6409: } ! 6410: } ! 6411: } ! 6412: break; ! 6413: } ! 6414: case 6: /* method */ ! 6415: sqlite3_result_int(ctx, pCDS->iCompression); ! 6416: break; ! 6417: default: /* z */ ! 6418: assert( i==7 ); ! 6419: sqlite3_result_int64(ctx, pCsr->iId); ! 6420: break; ! 6421: } ! 6422: ! 6423: return rc; ! 6424: } ! 6425: ! 6426: /* ! 6427: ** Return TRUE if the cursor is at EOF. ! 6428: */ ! 6429: static int zipfileEof(sqlite3_vtab_cursor *cur){ ! 6430: ZipfileCsr *pCsr = (ZipfileCsr*)cur; ! 6431: return pCsr->bEof; ! 6432: } ! 6433: ! 6434: /* ! 6435: ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size ! 6436: ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile ! 6437: ** is guaranteed to be a file-handle open on a zip file. ! 6438: ** ! 6439: ** This function attempts to locate the EOCD record within the zip archive ! 6440: ** and populate *pEOCD with the results of decoding it. SQLITE_OK is ! 6441: ** returned if successful. Otherwise, an SQLite error code is returned and ! 6442: ** an English language error message may be left in virtual-table pTab. ! 6443: */ ! 6444: static int zipfileReadEOCD( ! 6445: ZipfileTab *pTab, /* Return errors here */ ! 6446: const u8 *aBlob, /* Pointer to in-memory file image */ ! 6447: int nBlob, /* Size of aBlob[] in bytes */ ! 6448: FILE *pFile, /* Read from this file if aBlob==0 */ ! 6449: ZipfileEOCD *pEOCD /* Object to populate */ ! 6450: ){ ! 6451: u8 *aRead = pTab->aBuffer; /* Temporary buffer */ ! 6452: int nRead; /* Bytes to read from file */ ! 6453: int rc = SQLITE_OK; ! 6454: ! 6455: if( aBlob==0 ){ ! 6456: i64 iOff; /* Offset to read from */ ! 6457: i64 szFile; /* Total size of file in bytes */ ! 6458: fseek(pFile, 0, SEEK_END); ! 6459: szFile = (i64)ftell(pFile); ! 6460: if( szFile==0 ){ ! 6461: memset(pEOCD, 0, sizeof(ZipfileEOCD)); ! 6462: return SQLITE_OK; ! 6463: } ! 6464: nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE)); ! 6465: iOff = szFile - nRead; ! 6466: rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg); ! 6467: }else{ ! 6468: nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); ! 6469: aRead = (u8*)&aBlob[nBlob-nRead]; ! 6470: } ! 6471: ! 6472: if( rc==SQLITE_OK ){ ! 6473: int i; ! 6474: ! 6475: /* Scan backwards looking for the signature bytes */ ! 6476: for(i=nRead-20; i>=0; i--){ ! 6477: if( aRead[i]==0x50 && aRead[i+1]==0x4b ! 6478: && aRead[i+2]==0x05 && aRead[i+3]==0x06 ! 6479: ){ ! 6480: break; ! 6481: } ! 6482: } ! 6483: if( i<0 ){ ! 6484: pTab->base.zErrMsg = sqlite3_mprintf( ! 6485: "cannot find end of central directory record" ! 6486: ); ! 6487: return SQLITE_ERROR; ! 6488: } ! 6489: ! 6490: aRead += i+4; ! 6491: pEOCD->iDisk = zipfileRead16(aRead); ! 6492: pEOCD->iFirstDisk = zipfileRead16(aRead); ! 6493: pEOCD->nEntry = zipfileRead16(aRead); ! 6494: pEOCD->nEntryTotal = zipfileRead16(aRead); ! 6495: pEOCD->nSize = zipfileRead32(aRead); ! 6496: pEOCD->iOffset = zipfileRead32(aRead); ! 6497: } ! 6498: ! 6499: return rc; ! 6500: } ! 6501: ! 6502: /* ! 6503: ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry ! 6504: ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added ! 6505: ** to the end of the list. Otherwise, it is added to the list immediately ! 6506: ** before pBefore (which is guaranteed to be a part of said list). ! 6507: */ ! 6508: static void zipfileAddEntry( ! 6509: ZipfileTab *pTab, ! 6510: ZipfileEntry *pBefore, ! 6511: ZipfileEntry *pNew ! 6512: ){ ! 6513: assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) ); ! 6514: assert( pNew->pNext==0 ); ! 6515: if( pBefore==0 ){ ! 6516: if( pTab->pFirstEntry==0 ){ ! 6517: pTab->pFirstEntry = pTab->pLastEntry = pNew; ! 6518: }else{ ! 6519: assert( pTab->pLastEntry->pNext==0 ); ! 6520: pTab->pLastEntry->pNext = pNew; ! 6521: pTab->pLastEntry = pNew; ! 6522: } ! 6523: }else{ ! 6524: ZipfileEntry **pp; ! 6525: for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext)); ! 6526: pNew->pNext = pBefore; ! 6527: *pp = pNew; ! 6528: } ! 6529: } ! 6530: ! 6531: static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ ! 6532: ZipfileEOCD eocd; ! 6533: int rc; ! 6534: int i; ! 6535: i64 iOff; ! 6536: ! 6537: rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd); ! 6538: iOff = eocd.iOffset; ! 6539: for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){ ! 6540: ZipfileEntry *pNew = 0; ! 6541: rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew); ! 6542: ! 6543: if( rc==SQLITE_OK ){ ! 6544: zipfileAddEntry(pTab, 0, pNew); ! 6545: iOff += ZIPFILE_CDS_FIXED_SZ; ! 6546: iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment; ! 6547: } ! 6548: } ! 6549: return rc; ! 6550: } ! 6551: ! 6552: /* ! 6553: ** xFilter callback. ! 6554: */ ! 6555: static int zipfileFilter( ! 6556: sqlite3_vtab_cursor *cur, ! 6557: int idxNum, const char *idxStr, ! 6558: int argc, sqlite3_value **argv ! 6559: ){ ! 6560: ZipfileTab *pTab = (ZipfileTab*)cur->pVtab; ! 6561: ZipfileCsr *pCsr = (ZipfileCsr*)cur; ! 6562: const char *zFile = 0; /* Zip file to scan */ ! 6563: int rc = SQLITE_OK; /* Return Code */ ! 6564: int bInMemory = 0; /* True for an in-memory zipfile */ ! 6565: ! 6566: zipfileResetCursor(pCsr); ! 6567: ! 6568: if( pTab->zFile ){ ! 6569: zFile = pTab->zFile; ! 6570: }else if( idxNum==0 ){ ! 6571: zipfileCursorErr(pCsr, "zipfile() function requires an argument"); ! 6572: return SQLITE_ERROR; ! 6573: }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ ! 6574: const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); ! 6575: int nBlob = sqlite3_value_bytes(argv[0]); ! 6576: assert( pTab->pFirstEntry==0 ); ! 6577: rc = zipfileLoadDirectory(pTab, aBlob, nBlob); ! 6578: pCsr->pFreeEntry = pTab->pFirstEntry; ! 6579: pTab->pFirstEntry = pTab->pLastEntry = 0; ! 6580: if( rc!=SQLITE_OK ) return rc; ! 6581: bInMemory = 1; ! 6582: }else{ ! 6583: zFile = (const char*)sqlite3_value_text(argv[0]); ! 6584: } ! 6585: ! 6586: if( 0==pTab->pWriteFd && 0==bInMemory ){ ! 6587: pCsr->pFile = fopen(zFile, "rb"); ! 6588: if( pCsr->pFile==0 ){ ! 6589: zipfileCursorErr(pCsr, "cannot open file: %s", zFile); ! 6590: rc = SQLITE_ERROR; ! 6591: }else{ ! 6592: rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd); ! 6593: if( rc==SQLITE_OK ){ ! 6594: if( pCsr->eocd.nEntry==0 ){ ! 6595: pCsr->bEof = 1; ! 6596: }else{ ! 6597: pCsr->iNextOff = pCsr->eocd.iOffset; ! 6598: rc = zipfileNext(cur); ! 6599: } ! 6600: } ! 6601: } ! 6602: }else{ ! 6603: pCsr->bNoop = 1; ! 6604: pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry; ! 6605: rc = zipfileNext(cur); ! 6606: } ! 6607: ! 6608: return rc; ! 6609: } ! 6610: ! 6611: /* ! 6612: ** xBestIndex callback. ! 6613: */ ! 6614: static int zipfileBestIndex( ! 6615: sqlite3_vtab *tab, ! 6616: sqlite3_index_info *pIdxInfo ! 6617: ){ ! 6618: int i; ! 6619: int idx = -1; ! 6620: int unusable = 0; ! 6621: ! 6622: for(i=0; i<pIdxInfo->nConstraint; i++){ ! 6623: const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; ! 6624: if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; ! 6625: if( pCons->usable==0 ){ ! 6626: unusable = 1; ! 6627: }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ! 6628: idx = i; ! 6629: } ! 6630: } ! 6631: pIdxInfo->estimatedCost = 1000.0; ! 6632: if( idx>=0 ){ ! 6633: pIdxInfo->aConstraintUsage[idx].argvIndex = 1; ! 6634: pIdxInfo->aConstraintUsage[idx].omit = 1; ! 6635: pIdxInfo->idxNum = 1; ! 6636: }else if( unusable ){ ! 6637: return SQLITE_CONSTRAINT; ! 6638: } ! 6639: return SQLITE_OK; ! 6640: } ! 6641: ! 6642: static ZipfileEntry *zipfileNewEntry(const char *zPath){ ! 6643: ZipfileEntry *pNew; ! 6644: pNew = sqlite3_malloc(sizeof(ZipfileEntry)); ! 6645: if( pNew ){ ! 6646: memset(pNew, 0, sizeof(ZipfileEntry)); ! 6647: pNew->cds.zFile = sqlite3_mprintf("%s", zPath); ! 6648: if( pNew->cds.zFile==0 ){ ! 6649: sqlite3_free(pNew); ! 6650: pNew = 0; ! 6651: } ! 6652: } ! 6653: return pNew; ! 6654: } ! 6655: ! 6656: static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){ ! 6657: ZipfileCDS *pCds = &pEntry->cds; ! 6658: u8 *a = aBuf; ! 6659: ! 6660: pCds->nExtra = 9; ! 6661: ! 6662: /* Write the LFH itself */ ! 6663: zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH); ! 6664: zipfileWrite16(a, pCds->iVersionExtract); ! 6665: zipfileWrite16(a, pCds->flags); ! 6666: zipfileWrite16(a, pCds->iCompression); ! 6667: zipfileWrite16(a, pCds->mTime); ! 6668: zipfileWrite16(a, pCds->mDate); ! 6669: zipfileWrite32(a, pCds->crc32); ! 6670: zipfileWrite32(a, pCds->szCompressed); ! 6671: zipfileWrite32(a, pCds->szUncompressed); ! 6672: zipfileWrite16(a, (u16)pCds->nFile); ! 6673: zipfileWrite16(a, pCds->nExtra); ! 6674: assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] ); ! 6675: ! 6676: /* Add the file name */ ! 6677: memcpy(a, pCds->zFile, (int)pCds->nFile); ! 6678: a += (int)pCds->nFile; ! 6679: ! 6680: /* The "extra" data */ ! 6681: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); ! 6682: zipfileWrite16(a, 5); ! 6683: *a++ = 0x01; ! 6684: zipfileWrite32(a, pEntry->mUnixTime); ! 6685: ! 6686: return a-aBuf; ! 6687: } ! 6688: ! 6689: static int zipfileAppendEntry( ! 6690: ZipfileTab *pTab, ! 6691: ZipfileEntry *pEntry, ! 6692: const u8 *pData, ! 6693: int nData ! 6694: ){ ! 6695: u8 *aBuf = pTab->aBuffer; ! 6696: int nBuf; ! 6697: int rc; ! 6698: ! 6699: nBuf = zipfileSerializeLFH(pEntry, aBuf); ! 6700: rc = zipfileAppendData(pTab, aBuf, nBuf); ! 6701: if( rc==SQLITE_OK ){ ! 6702: pEntry->iDataOff = pTab->szCurrent; ! 6703: rc = zipfileAppendData(pTab, pData, nData); ! 6704: } ! 6705: ! 6706: return rc; ! 6707: } ! 6708: ! 6709: static int zipfileGetMode( ! 6710: sqlite3_value *pVal, ! 6711: int bIsDir, /* If true, default to directory */ ! 6712: u32 *pMode, /* OUT: Mode value */ ! 6713: char **pzErr /* OUT: Error message */ ! 6714: ){ ! 6715: const char *z = (const char*)sqlite3_value_text(pVal); ! 6716: u32 mode = 0; ! 6717: if( z==0 ){ ! 6718: mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)); ! 6719: }else if( z[0]>='0' && z[0]<='9' ){ ! 6720: mode = (unsigned int)sqlite3_value_int(pVal); ! 6721: }else{ ! 6722: const char zTemplate[11] = "-rwxrwxrwx"; ! 6723: int i; ! 6724: if( strlen(z)!=10 ) goto parse_error; ! 6725: switch( z[0] ){ ! 6726: case '-': mode |= S_IFREG; break; ! 6727: case 'd': mode |= S_IFDIR; break; ! 6728: case 'l': mode |= S_IFLNK; break; ! 6729: default: goto parse_error; ! 6730: } ! 6731: for(i=1; i<10; i++){ ! 6732: if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); ! 6733: else if( z[i]!='-' ) goto parse_error; ! 6734: } ! 6735: } ! 6736: if( ((mode & S_IFDIR)==0)==bIsDir ){ ! 6737: /* The "mode" attribute is a directory, but data has been specified. ! 6738: ** Or vice-versa - no data but "mode" is a file or symlink. */ ! 6739: *pzErr = sqlite3_mprintf("zipfile: mode does not match data"); ! 6740: return SQLITE_CONSTRAINT; ! 6741: } ! 6742: *pMode = mode; ! 6743: return SQLITE_OK; ! 6744: ! 6745: parse_error: ! 6746: *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); ! 6747: return SQLITE_ERROR; ! 6748: } ! 6749: ! 6750: /* ! 6751: ** Both (const char*) arguments point to nul-terminated strings. Argument ! 6752: ** nB is the value of strlen(zB). This function returns 0 if the strings are ! 6753: ** identical, ignoring any trailing '/' character in either path. */ ! 6754: static int zipfileComparePath(const char *zA, const char *zB, int nB){ ! 6755: int nA = (int)strlen(zA); ! 6756: if( nA>0 && zA[nA-1]=='/' ) nA--; ! 6757: if( nB>0 && zB[nB-1]=='/' ) nB--; ! 6758: if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; ! 6759: return 1; ! 6760: } ! 6761: ! 6762: static int zipfileBegin(sqlite3_vtab *pVtab){ ! 6763: ZipfileTab *pTab = (ZipfileTab*)pVtab; ! 6764: int rc = SQLITE_OK; ! 6765: ! 6766: assert( pTab->pWriteFd==0 ); ! 6767: if( pTab->zFile==0 || pTab->zFile[0]==0 ){ ! 6768: pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); ! 6769: return SQLITE_ERROR; ! 6770: } ! 6771: ! 6772: /* Open a write fd on the file. Also load the entire central directory ! 6773: ** structure into memory. During the transaction any new file data is ! 6774: ** appended to the archive file, but the central directory is accumulated ! 6775: ** in main-memory until the transaction is committed. */ ! 6776: pTab->pWriteFd = fopen(pTab->zFile, "ab+"); ! 6777: if( pTab->pWriteFd==0 ){ ! 6778: pTab->base.zErrMsg = sqlite3_mprintf( ! 6779: "zipfile: failed to open file %s for writing", pTab->zFile ! 6780: ); ! 6781: rc = SQLITE_ERROR; ! 6782: }else{ ! 6783: fseek(pTab->pWriteFd, 0, SEEK_END); ! 6784: pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); ! 6785: rc = zipfileLoadDirectory(pTab, 0, 0); ! 6786: } ! 6787: ! 6788: if( rc!=SQLITE_OK ){ ! 6789: zipfileCleanupTransaction(pTab); ! 6790: } ! 6791: ! 6792: return rc; ! 6793: } ! 6794: ! 6795: /* ! 6796: ** Return the current time as a 32-bit timestamp in UNIX epoch format (like ! 6797: ** time(2)). ! 6798: */ ! 6799: static u32 zipfileTime(void){ ! 6800: sqlite3_vfs *pVfs = sqlite3_vfs_find(0); ! 6801: u32 ret; ! 6802: if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ ! 6803: i64 ms; ! 6804: pVfs->xCurrentTimeInt64(pVfs, &ms); ! 6805: ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); ! 6806: }else{ ! 6807: double day; ! 6808: pVfs->xCurrentTime(pVfs, &day); ! 6809: ret = (u32)((day - 2440587.5) * 86400); ! 6810: } ! 6811: return ret; ! 6812: } ! 6813: ! 6814: /* ! 6815: ** Return a 32-bit timestamp in UNIX epoch format. ! 6816: ** ! 6817: ** If the value passed as the only argument is either NULL or an SQL NULL, ! 6818: ** return the current time. Otherwise, return the value stored in (*pVal) ! 6819: ** cast to a 32-bit unsigned integer. ! 6820: */ ! 6821: static u32 zipfileGetTime(sqlite3_value *pVal){ ! 6822: if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ ! 6823: return zipfileTime(); ! 6824: } ! 6825: return (u32)sqlite3_value_int64(pVal); ! 6826: } ! 6827: ! 6828: /* ! 6829: ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry ! 6830: ** linked list. Remove it from the list and free the object. ! 6831: */ ! 6832: static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){ ! 6833: if( pOld ){ ! 6834: ZipfileEntry **pp; ! 6835: for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext)); ! 6836: *pp = (*pp)->pNext; ! 6837: zipfileEntryFree(pOld); ! 6838: } ! 6839: } ! 6840: ! 6841: /* ! 6842: ** xUpdate method. ! 6843: */ ! 6844: static int zipfileUpdate( ! 6845: sqlite3_vtab *pVtab, ! 6846: int nVal, ! 6847: sqlite3_value **apVal, ! 6848: sqlite_int64 *pRowid ! 6849: ){ ! 6850: ZipfileTab *pTab = (ZipfileTab*)pVtab; ! 6851: int rc = SQLITE_OK; /* Return Code */ ! 6852: ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ ! 6853: ! 6854: u32 mode = 0; /* Mode for new entry */ ! 6855: u32 mTime = 0; /* Modification time for new entry */ ! 6856: i64 sz = 0; /* Uncompressed size */ ! 6857: const char *zPath = 0; /* Path for new entry */ ! 6858: int nPath = 0; /* strlen(zPath) */ ! 6859: const u8 *pData = 0; /* Pointer to buffer containing content */ ! 6860: int nData = 0; /* Size of pData buffer in bytes */ ! 6861: int iMethod = 0; /* Compression method for new entry */ ! 6862: u8 *pFree = 0; /* Free this */ ! 6863: char *zFree = 0; /* Also free this */ ! 6864: ZipfileEntry *pOld = 0; ! 6865: ZipfileEntry *pOld2 = 0; ! 6866: int bUpdate = 0; /* True for an update that modifies "name" */ ! 6867: int bIsDir = 0; ! 6868: u32 iCrc32 = 0; ! 6869: ! 6870: if( pTab->pWriteFd==0 ){ ! 6871: rc = zipfileBegin(pVtab); ! 6872: if( rc!=SQLITE_OK ) return rc; ! 6873: } ! 6874: ! 6875: /* If this is a DELETE or UPDATE, find the archive entry to delete. */ ! 6876: if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ ! 6877: const char *zDelete = (const char*)sqlite3_value_text(apVal[0]); ! 6878: int nDelete = (int)strlen(zDelete); ! 6879: if( nVal>1 ){ ! 6880: const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]); ! 6881: if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){ ! 6882: bUpdate = 1; ! 6883: } ! 6884: } ! 6885: for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){ ! 6886: if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){ ! 6887: break; ! 6888: } ! 6889: assert( pOld->pNext ); ! 6890: } ! 6891: } ! 6892: ! 6893: if( nVal>1 ){ ! 6894: /* Check that "sz" and "rawdata" are both NULL: */ ! 6895: if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){ ! 6896: zipfileTableErr(pTab, "sz must be NULL"); ! 6897: rc = SQLITE_CONSTRAINT; ! 6898: } ! 6899: if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){ ! 6900: zipfileTableErr(pTab, "rawdata must be NULL"); ! 6901: rc = SQLITE_CONSTRAINT; ! 6902: } ! 6903: ! 6904: if( rc==SQLITE_OK ){ ! 6905: if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){ ! 6906: /* data=NULL. A directory */ ! 6907: bIsDir = 1; ! 6908: }else{ ! 6909: /* Value specified for "data", and possibly "method". This must be ! 6910: ** a regular file or a symlink. */ ! 6911: const u8 *aIn = sqlite3_value_blob(apVal[7]); ! 6912: int nIn = sqlite3_value_bytes(apVal[7]); ! 6913: int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; ! 6914: ! 6915: iMethod = sqlite3_value_int(apVal[8]); ! 6916: sz = nIn; ! 6917: pData = aIn; ! 6918: nData = nIn; ! 6919: if( iMethod!=0 && iMethod!=8 ){ ! 6920: zipfileTableErr(pTab, "unknown compression method: %d", iMethod); ! 6921: rc = SQLITE_CONSTRAINT; ! 6922: }else{ ! 6923: if( bAuto || iMethod ){ ! 6924: int nCmp; ! 6925: rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg); ! 6926: if( rc==SQLITE_OK ){ ! 6927: if( iMethod || nCmp<nIn ){ ! 6928: iMethod = 8; ! 6929: pData = pFree; ! 6930: nData = nCmp; ! 6931: } ! 6932: } ! 6933: } ! 6934: iCrc32 = crc32(0, aIn, nIn); ! 6935: } ! 6936: } ! 6937: } ! 6938: ! 6939: if( rc==SQLITE_OK ){ ! 6940: rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg); ! 6941: } ! 6942: ! 6943: if( rc==SQLITE_OK ){ ! 6944: zPath = (const char*)sqlite3_value_text(apVal[2]); ! 6945: if( zPath==0 ) zPath = ""; ! 6946: nPath = (int)strlen(zPath); ! 6947: mTime = zipfileGetTime(apVal[4]); ! 6948: } ! 6949: ! 6950: if( rc==SQLITE_OK && bIsDir ){ ! 6951: /* For a directory, check that the last character in the path is a ! 6952: ** '/'. This appears to be required for compatibility with info-zip ! 6953: ** (the unzip command on unix). It does not create directories ! 6954: ** otherwise. */ ! 6955: if( nPath<=0 || zPath[nPath-1]!='/' ){ ! 6956: zFree = sqlite3_mprintf("%s/", zPath); ! 6957: zPath = (const char*)zFree; ! 6958: if( zFree==0 ){ ! 6959: rc = SQLITE_NOMEM; ! 6960: nPath = 0; ! 6961: }else{ ! 6962: nPath = (int)strlen(zPath); ! 6963: } ! 6964: } ! 6965: } ! 6966: ! 6967: /* Check that we're not inserting a duplicate entry -OR- updating an ! 6968: ** entry with a path, thereby making it into a duplicate. */ ! 6969: if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ ! 6970: ZipfileEntry *p; ! 6971: for(p=pTab->pFirstEntry; p; p=p->pNext){ ! 6972: if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ ! 6973: switch( sqlite3_vtab_on_conflict(pTab->db) ){ ! 6974: case SQLITE_IGNORE: { ! 6975: goto zipfile_update_done; ! 6976: } ! 6977: case SQLITE_REPLACE: { ! 6978: pOld2 = p; ! 6979: break; ! 6980: } ! 6981: default: { ! 6982: zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath); ! 6983: rc = SQLITE_CONSTRAINT; ! 6984: break; ! 6985: } ! 6986: } ! 6987: break; ! 6988: } ! 6989: } ! 6990: } ! 6991: ! 6992: if( rc==SQLITE_OK ){ ! 6993: /* Create the new CDS record. */ ! 6994: pNew = zipfileNewEntry(zPath); ! 6995: if( pNew==0 ){ ! 6996: rc = SQLITE_NOMEM; ! 6997: }else{ ! 6998: pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ! 6999: pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; ! 7000: pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS; ! 7001: pNew->cds.iCompression = (u16)iMethod; ! 7002: zipfileMtimeToDos(&pNew->cds, mTime); ! 7003: pNew->cds.crc32 = iCrc32; ! 7004: pNew->cds.szCompressed = nData; ! 7005: pNew->cds.szUncompressed = (u32)sz; ! 7006: pNew->cds.iExternalAttr = (mode<<16); ! 7007: pNew->cds.iOffset = (u32)pTab->szCurrent; ! 7008: pNew->cds.nFile = (u16)nPath; ! 7009: pNew->mUnixTime = (u32)mTime; ! 7010: rc = zipfileAppendEntry(pTab, pNew, pData, nData); ! 7011: zipfileAddEntry(pTab, pOld, pNew); ! 7012: } ! 7013: } ! 7014: } ! 7015: ! 7016: if( rc==SQLITE_OK && (pOld || pOld2) ){ ! 7017: ZipfileCsr *pCsr; ! 7018: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ ! 7019: if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){ ! 7020: pCsr->pCurrent = pCsr->pCurrent->pNext; ! 7021: pCsr->bNoop = 1; ! 7022: } ! 7023: } ! 7024: ! 7025: zipfileRemoveEntryFromList(pTab, pOld); ! 7026: zipfileRemoveEntryFromList(pTab, pOld2); ! 7027: } ! 7028: ! 7029: zipfile_update_done: ! 7030: sqlite3_free(pFree); ! 7031: sqlite3_free(zFree); ! 7032: return rc; ! 7033: } ! 7034: ! 7035: static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){ ! 7036: u8 *a = aBuf; ! 7037: zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD); ! 7038: zipfileWrite16(a, p->iDisk); ! 7039: zipfileWrite16(a, p->iFirstDisk); ! 7040: zipfileWrite16(a, p->nEntry); ! 7041: zipfileWrite16(a, p->nEntryTotal); ! 7042: zipfileWrite32(a, p->nSize); ! 7043: zipfileWrite32(a, p->iOffset); ! 7044: zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/ ! 7045: ! 7046: return a-aBuf; ! 7047: } ! 7048: ! 7049: static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ ! 7050: int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer); ! 7051: assert( nBuf==ZIPFILE_EOCD_FIXED_SZ ); ! 7052: return zipfileAppendData(pTab, pTab->aBuffer, nBuf); ! 7053: } ! 7054: ! 7055: /* ! 7056: ** Serialize the CDS structure into buffer aBuf[]. Return the number ! 7057: ** of bytes written. ! 7058: */ ! 7059: static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){ ! 7060: u8 *a = aBuf; ! 7061: ZipfileCDS *pCDS = &pEntry->cds; ! 7062: ! 7063: if( pEntry->aExtra==0 ){ ! 7064: pCDS->nExtra = 9; ! 7065: } ! 7066: ! 7067: zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS); ! 7068: zipfileWrite16(a, pCDS->iVersionMadeBy); ! 7069: zipfileWrite16(a, pCDS->iVersionExtract); ! 7070: zipfileWrite16(a, pCDS->flags); ! 7071: zipfileWrite16(a, pCDS->iCompression); ! 7072: zipfileWrite16(a, pCDS->mTime); ! 7073: zipfileWrite16(a, pCDS->mDate); ! 7074: zipfileWrite32(a, pCDS->crc32); ! 7075: zipfileWrite32(a, pCDS->szCompressed); ! 7076: zipfileWrite32(a, pCDS->szUncompressed); ! 7077: assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); ! 7078: zipfileWrite16(a, pCDS->nFile); ! 7079: zipfileWrite16(a, pCDS->nExtra); ! 7080: zipfileWrite16(a, pCDS->nComment); ! 7081: zipfileWrite16(a, pCDS->iDiskStart); ! 7082: zipfileWrite16(a, pCDS->iInternalAttr); ! 7083: zipfileWrite32(a, pCDS->iExternalAttr); ! 7084: zipfileWrite32(a, pCDS->iOffset); ! 7085: ! 7086: memcpy(a, pCDS->zFile, pCDS->nFile); ! 7087: a += pCDS->nFile; ! 7088: ! 7089: if( pEntry->aExtra ){ ! 7090: int n = (int)pCDS->nExtra + (int)pCDS->nComment; ! 7091: memcpy(a, pEntry->aExtra, n); ! 7092: a += n; ! 7093: }else{ ! 7094: assert( pCDS->nExtra==9 ); ! 7095: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); ! 7096: zipfileWrite16(a, 5); ! 7097: *a++ = 0x01; ! 7098: zipfileWrite32(a, pEntry->mUnixTime); ! 7099: } ! 7100: ! 7101: return a-aBuf; ! 7102: } ! 7103: ! 7104: static int zipfileCommit(sqlite3_vtab *pVtab){ ! 7105: ZipfileTab *pTab = (ZipfileTab*)pVtab; ! 7106: int rc = SQLITE_OK; ! 7107: if( pTab->pWriteFd ){ ! 7108: i64 iOffset = pTab->szCurrent; ! 7109: ZipfileEntry *p; ! 7110: ZipfileEOCD eocd; ! 7111: int nEntry = 0; ! 7112: ! 7113: /* Write out all entries */ ! 7114: for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){ ! 7115: int n = zipfileSerializeCDS(p, pTab->aBuffer); ! 7116: rc = zipfileAppendData(pTab, pTab->aBuffer, n); ! 7117: nEntry++; ! 7118: } ! 7119: ! 7120: /* Write out the EOCD record */ ! 7121: eocd.iDisk = 0; ! 7122: eocd.iFirstDisk = 0; ! 7123: eocd.nEntry = (u16)nEntry; ! 7124: eocd.nEntryTotal = (u16)nEntry; ! 7125: eocd.nSize = (u32)(pTab->szCurrent - iOffset); ! 7126: eocd.iOffset = (u32)iOffset; ! 7127: rc = zipfileAppendEOCD(pTab, &eocd); ! 7128: ! 7129: zipfileCleanupTransaction(pTab); ! 7130: } ! 7131: return rc; ! 7132: } ! 7133: ! 7134: static int zipfileRollback(sqlite3_vtab *pVtab){ ! 7135: return zipfileCommit(pVtab); ! 7136: } ! 7137: ! 7138: static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){ ! 7139: ZipfileCsr *pCsr; ! 7140: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ ! 7141: if( iId==pCsr->iId ) break; ! 7142: } ! 7143: return pCsr; ! 7144: } ! 7145: ! 7146: static void zipfileFunctionCds( ! 7147: sqlite3_context *context, ! 7148: int argc, ! 7149: sqlite3_value **argv ! 7150: ){ ! 7151: ZipfileCsr *pCsr; ! 7152: ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context); ! 7153: assert( argc>0 ); ! 7154: ! 7155: pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0])); ! 7156: if( pCsr ){ ! 7157: ZipfileCDS *p = &pCsr->pCurrent->cds; ! 7158: char *zRes = sqlite3_mprintf("{" ! 7159: "\"version-made-by\" : %u, " ! 7160: "\"version-to-extract\" : %u, " ! 7161: "\"flags\" : %u, " ! 7162: "\"compression\" : %u, " ! 7163: "\"time\" : %u, " ! 7164: "\"date\" : %u, " ! 7165: "\"crc32\" : %u, " ! 7166: "\"compressed-size\" : %u, " ! 7167: "\"uncompressed-size\" : %u, " ! 7168: "\"file-name-length\" : %u, " ! 7169: "\"extra-field-length\" : %u, " ! 7170: "\"file-comment-length\" : %u, " ! 7171: "\"disk-number-start\" : %u, " ! 7172: "\"internal-attr\" : %u, " ! 7173: "\"external-attr\" : %u, " ! 7174: "\"offset\" : %u }", ! 7175: (u32)p->iVersionMadeBy, (u32)p->iVersionExtract, ! 7176: (u32)p->flags, (u32)p->iCompression, ! 7177: (u32)p->mTime, (u32)p->mDate, ! 7178: (u32)p->crc32, (u32)p->szCompressed, ! 7179: (u32)p->szUncompressed, (u32)p->nFile, ! 7180: (u32)p->nExtra, (u32)p->nComment, ! 7181: (u32)p->iDiskStart, (u32)p->iInternalAttr, ! 7182: (u32)p->iExternalAttr, (u32)p->iOffset ! 7183: ); ! 7184: ! 7185: if( zRes==0 ){ ! 7186: sqlite3_result_error_nomem(context); ! 7187: }else{ ! 7188: sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT); ! 7189: sqlite3_free(zRes); ! 7190: } ! 7191: } ! 7192: } ! 7193: ! 7194: /* ! 7195: ** xFindFunction method. ! 7196: */ ! 7197: static int zipfileFindFunction( ! 7198: sqlite3_vtab *pVtab, /* Virtual table handle */ ! 7199: int nArg, /* Number of SQL function arguments */ ! 7200: const char *zName, /* Name of SQL function */ ! 7201: void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ ! 7202: void **ppArg /* OUT: User data for *pxFunc */ ! 7203: ){ ! 7204: if( sqlite3_stricmp("zipfile_cds", zName)==0 ){ ! 7205: *pxFunc = zipfileFunctionCds; ! 7206: *ppArg = (void*)pVtab; ! 7207: return 1; ! 7208: } ! 7209: return 0; ! 7210: } ! 7211: ! 7212: typedef struct ZipfileBuffer ZipfileBuffer; ! 7213: struct ZipfileBuffer { ! 7214: u8 *a; /* Pointer to buffer */ ! 7215: int n; /* Size of buffer in bytes */ ! 7216: int nAlloc; /* Byte allocated at a[] */ ! 7217: }; ! 7218: ! 7219: typedef struct ZipfileCtx ZipfileCtx; ! 7220: struct ZipfileCtx { ! 7221: int nEntry; ! 7222: ZipfileBuffer body; ! 7223: ZipfileBuffer cds; ! 7224: }; ! 7225: ! 7226: static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ ! 7227: if( pBuf->n+nByte>pBuf->nAlloc ){ ! 7228: u8 *aNew; ! 7229: sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; ! 7230: int nReq = pBuf->n + nByte; ! 7231: ! 7232: while( nNew<nReq ) nNew = nNew*2; ! 7233: aNew = sqlite3_realloc64(pBuf->a, nNew); ! 7234: if( aNew==0 ) return SQLITE_NOMEM; ! 7235: pBuf->a = aNew; ! 7236: pBuf->nAlloc = (int)nNew; ! 7237: } ! 7238: return SQLITE_OK; ! 7239: } ! 7240: ! 7241: /* ! 7242: ** xStep() callback for the zipfile() aggregate. This can be called in ! 7243: ** any of the following ways: ! 7244: ** ! 7245: ** SELECT zipfile(name,data) ... ! 7246: ** SELECT zipfile(name,mode,mtime,data) ... ! 7247: ** SELECT zipfile(name,mode,mtime,data,method) ... ! 7248: */ ! 7249: void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ ! 7250: ZipfileCtx *p; /* Aggregate function context */ ! 7251: ZipfileEntry e; /* New entry to add to zip archive */ ! 7252: ! 7253: sqlite3_value *pName = 0; ! 7254: sqlite3_value *pMode = 0; ! 7255: sqlite3_value *pMtime = 0; ! 7256: sqlite3_value *pData = 0; ! 7257: sqlite3_value *pMethod = 0; ! 7258: ! 7259: int bIsDir = 0; ! 7260: u32 mode; ! 7261: int rc = SQLITE_OK; ! 7262: char *zErr = 0; ! 7263: ! 7264: int iMethod = -1; /* Compression method to use (0 or 8) */ ! 7265: ! 7266: const u8 *aData = 0; /* Possibly compressed data for new entry */ ! 7267: int nData = 0; /* Size of aData[] in bytes */ ! 7268: int szUncompressed = 0; /* Size of data before compression */ ! 7269: u8 *aFree = 0; /* Free this before returning */ ! 7270: u32 iCrc32 = 0; /* crc32 of uncompressed data */ ! 7271: ! 7272: char *zName = 0; /* Path (name) of new entry */ ! 7273: int nName = 0; /* Size of zName in bytes */ ! 7274: char *zFree = 0; /* Free this before returning */ ! 7275: int nByte; ! 7276: ! 7277: memset(&e, 0, sizeof(e)); ! 7278: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); ! 7279: if( p==0 ) return; ! 7280: ! 7281: /* Martial the arguments into stack variables */ ! 7282: if( nVal!=2 && nVal!=4 && nVal!=5 ){ ! 7283: zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()"); ! 7284: rc = SQLITE_ERROR; ! 7285: goto zipfile_step_out; ! 7286: } ! 7287: pName = apVal[0]; ! 7288: if( nVal==2 ){ ! 7289: pData = apVal[1]; ! 7290: }else{ ! 7291: pMode = apVal[1]; ! 7292: pMtime = apVal[2]; ! 7293: pData = apVal[3]; ! 7294: if( nVal==5 ){ ! 7295: pMethod = apVal[4]; ! 7296: } ! 7297: } ! 7298: ! 7299: /* Check that the 'name' parameter looks ok. */ ! 7300: zName = (char*)sqlite3_value_text(pName); ! 7301: nName = sqlite3_value_bytes(pName); ! 7302: if( zName==0 ){ ! 7303: zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL"); ! 7304: rc = SQLITE_ERROR; ! 7305: goto zipfile_step_out; ! 7306: } ! 7307: ! 7308: /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use ! 7309: ** deflate compression) or NULL (choose automatically). */ ! 7310: if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){ ! 7311: iMethod = (int)sqlite3_value_int64(pMethod); ! 7312: if( iMethod!=0 && iMethod!=8 ){ ! 7313: zErr = sqlite3_mprintf("illegal method value: %d", iMethod); ! 7314: rc = SQLITE_ERROR; ! 7315: goto zipfile_step_out; ! 7316: } ! 7317: } ! 7318: ! 7319: /* Now inspect the data. If this is NULL, then the new entry must be a ! 7320: ** directory. Otherwise, figure out whether or not the data should ! 7321: ** be deflated or simply stored in the zip archive. */ ! 7322: if( sqlite3_value_type(pData)==SQLITE_NULL ){ ! 7323: bIsDir = 1; ! 7324: iMethod = 0; ! 7325: }else{ ! 7326: aData = sqlite3_value_blob(pData); ! 7327: szUncompressed = nData = sqlite3_value_bytes(pData); ! 7328: iCrc32 = crc32(0, aData, nData); ! 7329: if( iMethod<0 || iMethod==8 ){ ! 7330: int nOut = 0; ! 7331: rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr); ! 7332: if( rc!=SQLITE_OK ){ ! 7333: goto zipfile_step_out; ! 7334: } ! 7335: if( iMethod==8 || nOut<nData ){ ! 7336: aData = aFree; ! 7337: nData = nOut; ! 7338: iMethod = 8; ! 7339: }else{ ! 7340: iMethod = 0; ! 7341: } ! 7342: } ! 7343: } ! 7344: ! 7345: /* Decode the "mode" argument. */ ! 7346: rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr); ! 7347: if( rc ) goto zipfile_step_out; ! 7348: ! 7349: /* Decode the "mtime" argument. */ ! 7350: e.mUnixTime = zipfileGetTime(pMtime); ! 7351: ! 7352: /* If this is a directory entry, ensure that there is exactly one '/' ! 7353: ** at the end of the path. Or, if this is not a directory and the path ! 7354: ** ends in '/' it is an error. */ ! 7355: if( bIsDir==0 ){ ! 7356: if( nName>0 && zName[nName-1]=='/' ){ ! 7357: zErr = sqlite3_mprintf("non-directory name must not end with /"); ! 7358: rc = SQLITE_ERROR; ! 7359: goto zipfile_step_out; ! 7360: } ! 7361: }else{ ! 7362: if( nName==0 || zName[nName-1]!='/' ){ ! 7363: zName = zFree = sqlite3_mprintf("%s/", zName); ! 7364: if( zName==0 ){ ! 7365: rc = SQLITE_NOMEM; ! 7366: goto zipfile_step_out; ! 7367: } ! 7368: nName = (int)strlen(zName); ! 7369: }else{ ! 7370: while( nName>1 && zName[nName-2]=='/' ) nName--; ! 7371: } ! 7372: } ! 7373: ! 7374: /* Assemble the ZipfileEntry object for the new zip archive entry */ ! 7375: e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ! 7376: e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; ! 7377: e.cds.flags = ZIPFILE_NEWENTRY_FLAGS; ! 7378: e.cds.iCompression = (u16)iMethod; ! 7379: zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime); ! 7380: e.cds.crc32 = iCrc32; ! 7381: e.cds.szCompressed = nData; ! 7382: e.cds.szUncompressed = szUncompressed; ! 7383: e.cds.iExternalAttr = (mode<<16); ! 7384: e.cds.iOffset = p->body.n; ! 7385: e.cds.nFile = (u16)nName; ! 7386: e.cds.zFile = zName; ! 7387: ! 7388: /* Append the LFH to the body of the new archive */ ! 7389: nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9; ! 7390: if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out; ! 7391: p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]); ! 7392: ! 7393: /* Append the data to the body of the new archive */ ! 7394: if( nData>0 ){ ! 7395: if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out; ! 7396: memcpy(&p->body.a[p->body.n], aData, nData); ! 7397: p->body.n += nData; ! 7398: } ! 7399: ! 7400: /* Append the CDS record to the directory of the new archive */ ! 7401: nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9; ! 7402: if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out; ! 7403: p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]); ! 7404: ! 7405: /* Increment the count of entries in the archive */ ! 7406: p->nEntry++; ! 7407: ! 7408: zipfile_step_out: ! 7409: sqlite3_free(aFree); ! 7410: sqlite3_free(zFree); ! 7411: if( rc ){ ! 7412: if( zErr ){ ! 7413: sqlite3_result_error(pCtx, zErr, -1); ! 7414: }else{ ! 7415: sqlite3_result_error_code(pCtx, rc); ! 7416: } ! 7417: } ! 7418: sqlite3_free(zErr); ! 7419: } ! 7420: ! 7421: /* ! 7422: ** xFinalize() callback for zipfile aggregate function. ! 7423: */ ! 7424: void zipfileFinal(sqlite3_context *pCtx){ ! 7425: ZipfileCtx *p; ! 7426: ZipfileEOCD eocd; ! 7427: sqlite3_int64 nZip; ! 7428: u8 *aZip; ! 7429: ! 7430: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); ! 7431: if( p==0 ) return; ! 7432: if( p->nEntry>0 ){ ! 7433: memset(&eocd, 0, sizeof(eocd)); ! 7434: eocd.nEntry = (u16)p->nEntry; ! 7435: eocd.nEntryTotal = (u16)p->nEntry; ! 7436: eocd.nSize = p->cds.n; ! 7437: eocd.iOffset = p->body.n; ! 7438: ! 7439: nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; ! 7440: aZip = (u8*)sqlite3_malloc64(nZip); ! 7441: if( aZip==0 ){ ! 7442: sqlite3_result_error_nomem(pCtx); ! 7443: }else{ ! 7444: memcpy(aZip, p->body.a, p->body.n); ! 7445: memcpy(&aZip[p->body.n], p->cds.a, p->cds.n); ! 7446: zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]); ! 7447: sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree); ! 7448: } ! 7449: } ! 7450: ! 7451: sqlite3_free(p->body.a); ! 7452: sqlite3_free(p->cds.a); ! 7453: } ! 7454: ! 7455: ! 7456: /* ! 7457: ** Register the "zipfile" virtual table. ! 7458: */ ! 7459: static int zipfileRegister(sqlite3 *db){ ! 7460: static sqlite3_module zipfileModule = { ! 7461: 1, /* iVersion */ ! 7462: zipfileConnect, /* xCreate */ ! 7463: zipfileConnect, /* xConnect */ ! 7464: zipfileBestIndex, /* xBestIndex */ ! 7465: zipfileDisconnect, /* xDisconnect */ ! 7466: zipfileDisconnect, /* xDestroy */ ! 7467: zipfileOpen, /* xOpen - open a cursor */ ! 7468: zipfileClose, /* xClose - close a cursor */ ! 7469: zipfileFilter, /* xFilter - configure scan constraints */ ! 7470: zipfileNext, /* xNext - advance a cursor */ ! 7471: zipfileEof, /* xEof - check for end of scan */ ! 7472: zipfileColumn, /* xColumn - read data */ ! 7473: 0, /* xRowid - read data */ ! 7474: zipfileUpdate, /* xUpdate */ ! 7475: zipfileBegin, /* xBegin */ ! 7476: 0, /* xSync */ ! 7477: zipfileCommit, /* xCommit */ ! 7478: zipfileRollback, /* xRollback */ ! 7479: zipfileFindFunction, /* xFindMethod */ ! 7480: 0, /* xRename */ ! 7481: }; ! 7482: ! 7483: int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); ! 7484: if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1); ! 7485: if( rc==SQLITE_OK ){ ! 7486: rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, ! 7487: zipfileStep, zipfileFinal ! 7488: ); ! 7489: } ! 7490: return rc; ! 7491: } ! 7492: #else /* SQLITE_OMIT_VIRTUALTABLE */ ! 7493: # define zipfileRegister(x) SQLITE_OK ! 7494: #endif ! 7495: ! 7496: #ifdef _WIN32 ! 7497: ! 7498: #endif ! 7499: int sqlite3_zipfile_init( ! 7500: sqlite3 *db, ! 7501: char **pzErrMsg, ! 7502: const sqlite3_api_routines *pApi ! 7503: ){ ! 7504: SQLITE_EXTENSION_INIT2(pApi); ! 7505: (void)pzErrMsg; /* Unused parameter */ ! 7506: return zipfileRegister(db); ! 7507: } ! 7508: ! 7509: /************************* End ../ext/misc/zipfile.c ********************/ ! 7510: /************************* Begin ../ext/misc/sqlar.c ******************/ ! 7511: /* ! 7512: ** 2017-12-17 ! 7513: ** ! 7514: ** The author disclaims copyright to this source code. In place of ! 7515: ** a legal notice, here is a blessing: ! 7516: ** ! 7517: ** May you do good and not evil. ! 7518: ** May you find forgiveness for yourself and forgive others. ! 7519: ** May you share freely, never taking more than you give. ! 7520: ** ! 7521: ****************************************************************************** ! 7522: ** ! 7523: ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful ! 7524: ** for working with sqlar archives and used by the shell tool's built-in ! 7525: ** sqlar support. ! 7526: */ ! 7527: /* #include "sqlite3ext.h" */ ! 7528: SQLITE_EXTENSION_INIT1 ! 7529: #include <zlib.h> ! 7530: #include <assert.h> ! 7531: ! 7532: /* ! 7533: ** Implementation of the "sqlar_compress(X)" SQL function. ! 7534: ** ! 7535: ** If the type of X is SQLITE_BLOB, and compressing that blob using ! 7536: ** zlib utility function compress() yields a smaller blob, return the ! 7537: ** compressed blob. Otherwise, return a copy of X. ! 7538: ** ! 7539: ** SQLar uses the "zlib format" for compressed content. The zlib format ! 7540: ** contains a two-byte identification header and a four-byte checksum at ! 7541: ** the end. This is different from ZIP which uses the raw deflate format. ! 7542: ** ! 7543: ** Future enhancements to SQLar might add support for new compression formats. ! 7544: ** If so, those new formats will be identified by alternative headers in the ! 7545: ** compressed data. ! 7546: */ ! 7547: static void sqlarCompressFunc( ! 7548: sqlite3_context *context, ! 7549: int argc, ! 7550: sqlite3_value **argv ! 7551: ){ ! 7552: assert( argc==1 ); ! 7553: if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ ! 7554: const Bytef *pData = sqlite3_value_blob(argv[0]); ! 7555: uLong nData = sqlite3_value_bytes(argv[0]); ! 7556: uLongf nOut = compressBound(nData); ! 7557: Bytef *pOut; ! 7558: ! 7559: pOut = (Bytef*)sqlite3_malloc(nOut); ! 7560: if( pOut==0 ){ ! 7561: sqlite3_result_error_nomem(context); ! 7562: return; ! 7563: }else{ ! 7564: if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ ! 7565: sqlite3_result_error(context, "error in compress()", -1); ! 7566: }else if( nOut<nData ){ ! 7567: sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT); ! 7568: }else{ ! 7569: sqlite3_result_value(context, argv[0]); ! 7570: } ! 7571: sqlite3_free(pOut); ! 7572: } ! 7573: }else{ ! 7574: sqlite3_result_value(context, argv[0]); ! 7575: } ! 7576: } ! 7577: ! 7578: /* ! 7579: ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function ! 7580: ** ! 7581: ** Parameter SZ is interpreted as an integer. If it is less than or ! 7582: ** equal to zero, then this function returns a copy of X. Or, if ! 7583: ** SZ is equal to the size of X when interpreted as a blob, also ! 7584: ** return a copy of X. Otherwise, decompress blob X using zlib ! 7585: ** utility function uncompress() and return the results (another ! 7586: ** blob). ! 7587: */ ! 7588: static void sqlarUncompressFunc( ! 7589: sqlite3_context *context, ! 7590: int argc, ! 7591: sqlite3_value **argv ! 7592: ){ ! 7593: uLong nData; ! 7594: uLongf sz; ! 7595: ! 7596: assert( argc==2 ); ! 7597: sz = sqlite3_value_int(argv[1]); ! 7598: ! 7599: if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ ! 7600: sqlite3_result_value(context, argv[0]); ! 7601: }else{ ! 7602: const Bytef *pData= sqlite3_value_blob(argv[0]); ! 7603: Bytef *pOut = sqlite3_malloc(sz); ! 7604: if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ ! 7605: sqlite3_result_error(context, "error in uncompress()", -1); ! 7606: }else{ ! 7607: sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); ! 7608: } ! 7609: sqlite3_free(pOut); ! 7610: } ! 7611: } ! 7612: ! 7613: ! 7614: #ifdef _WIN32 ! 7615: ! 7616: #endif ! 7617: int sqlite3_sqlar_init( ! 7618: sqlite3 *db, ! 7619: char **pzErrMsg, ! 7620: const sqlite3_api_routines *pApi ! 7621: ){ ! 7622: int rc = SQLITE_OK; ! 7623: SQLITE_EXTENSION_INIT2(pApi); ! 7624: (void)pzErrMsg; /* Unused parameter */ ! 7625: rc = sqlite3_create_function(db, "sqlar_compress", 1, ! 7626: SQLITE_UTF8|SQLITE_INNOCUOUS, 0, ! 7627: sqlarCompressFunc, 0, 0); ! 7628: if( rc==SQLITE_OK ){ ! 7629: rc = sqlite3_create_function(db, "sqlar_uncompress", 2, ! 7630: SQLITE_UTF8|SQLITE_INNOCUOUS, 0, ! 7631: sqlarUncompressFunc, 0, 0); ! 7632: } ! 7633: return rc; ! 7634: } ! 7635: ! 7636: /************************* End ../ext/misc/sqlar.c ********************/ ! 7637: #endif ! 7638: /************************* Begin ../ext/expert/sqlite3expert.h ******************/ ! 7639: /* ! 7640: ** 2017 April 07 ! 7641: ** ! 7642: ** The author disclaims copyright to this source code. In place of ! 7643: ** a legal notice, here is a blessing: ! 7644: ** ! 7645: ** May you do good and not evil. ! 7646: ** May you find forgiveness for yourself and forgive others. ! 7647: ** May you share freely, never taking more than you give. ! 7648: ** ! 7649: ************************************************************************* ! 7650: */ ! 7651: #if !defined(SQLITEEXPERT_H) ! 7652: #define SQLITEEXPERT_H 1 ! 7653: /* #include "sqlite3.h" */ ! 7654: ! 7655: typedef struct sqlite3expert sqlite3expert; ! 7656: ! 7657: /* ! 7658: ** Create a new sqlite3expert object. ! 7659: ** ! 7660: ** If successful, a pointer to the new object is returned and (*pzErr) set ! 7661: ** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to ! 7662: ** an English-language error message. In this case it is the responsibility ! 7663: ** of the caller to eventually free the error message buffer using ! 7664: ** sqlite3_free(). ! 7665: */ ! 7666: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr); ! 7667: ! 7668: /* ! 7669: ** Configure an sqlite3expert object. ! 7670: ** ! 7671: ** EXPERT_CONFIG_SAMPLE: ! 7672: ** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for ! 7673: ** each candidate index. This involves scanning and sorting the entire ! 7674: ** contents of each user database table once for each candidate index ! 7675: ** associated with the table. For large databases, this can be ! 7676: ** prohibitively slow. This option allows the sqlite3expert object to ! 7677: ** be configured so that sqlite_stat1 data is instead generated based on a ! 7678: ** subset of each table, or so that no sqlite_stat1 data is used at all. ! 7679: ** ! 7680: ** A single integer argument is passed to this option. If the value is less ! 7681: ** than or equal to zero, then no sqlite_stat1 data is generated or used by ! 7682: ** the analysis - indexes are recommended based on the database schema only. ! 7683: ** Or, if the value is 100 or greater, complete sqlite_stat1 data is ! 7684: ** generated for each candidate index (this is the default). Finally, if the ! 7685: ** value falls between 0 and 100, then it represents the percentage of user ! 7686: ** table rows that should be considered when generating sqlite_stat1 data. ! 7687: ** ! 7688: ** Examples: ! 7689: ** ! 7690: ** // Do not generate any sqlite_stat1 data ! 7691: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0); ! 7692: ** ! 7693: ** // Generate sqlite_stat1 data based on 10% of the rows in each table. ! 7694: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10); ! 7695: */ ! 7696: int sqlite3_expert_config(sqlite3expert *p, int op, ...); ! 7697: ! 7698: #define EXPERT_CONFIG_SAMPLE 1 /* int */ ! 7699: ! 7700: /* ! 7701: ** Specify zero or more SQL statements to be included in the analysis. ! 7702: ** ! 7703: ** Buffer zSql must contain zero or more complete SQL statements. This ! 7704: ** function parses all statements contained in the buffer and adds them ! 7705: ** to the internal list of statements to analyze. If successful, SQLITE_OK ! 7706: ** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example ! 7707: ** due to a error in the SQL - an SQLite error code is returned and (*pzErr) ! 7708: ** may be set to point to an English language error message. In this case ! 7709: ** the caller is responsible for eventually freeing the error message buffer ! 7710: ** using sqlite3_free(). ! 7711: ** ! 7712: ** If an error does occur while processing one of the statements in the ! 7713: ** buffer passed as the second argument, none of the statements in the ! 7714: ** buffer are added to the analysis. ! 7715: ** ! 7716: ** This function must be called before sqlite3_expert_analyze(). If a call ! 7717: ** to this function is made on an sqlite3expert object that has already ! 7718: ** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned ! 7719: ** immediately and no statements are added to the analysis. ! 7720: */ ! 7721: int sqlite3_expert_sql( ! 7722: sqlite3expert *p, /* From a successful sqlite3_expert_new() */ ! 7723: const char *zSql, /* SQL statement(s) to add */ ! 7724: char **pzErr /* OUT: Error message (if any) */ ! 7725: ); ! 7726: ! 7727: ! 7728: /* ! 7729: ** This function is called after the sqlite3expert object has been configured ! 7730: ** with all SQL statements using sqlite3_expert_sql() to actually perform ! 7731: ** the analysis. Once this function has been called, it is not possible to ! 7732: ** add further SQL statements to the analysis. ! 7733: ** ! 7734: ** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if ! 7735: ** an error occurs, an SQLite error code is returned and (*pzErr) set to ! 7736: ** point to a buffer containing an English language error message. In this ! 7737: ** case it is the responsibility of the caller to eventually free the buffer ! 7738: ** using sqlite3_free(). ! 7739: ** ! 7740: ** If an error does occur within this function, the sqlite3expert object ! 7741: ** is no longer useful for any purpose. At that point it is no longer ! 7742: ** possible to add further SQL statements to the object or to re-attempt ! 7743: ** the analysis. The sqlite3expert object must still be freed using a call ! 7744: ** sqlite3_expert_destroy(). ! 7745: */ ! 7746: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr); ! 7747: ! 7748: /* ! 7749: ** Return the total number of statements loaded using sqlite3_expert_sql(). ! 7750: ** The total number of SQL statements may be different from the total number ! 7751: ** to calls to sqlite3_expert_sql(). ! 7752: */ ! 7753: int sqlite3_expert_count(sqlite3expert*); ! 7754: ! 7755: /* ! 7756: ** Return a component of the report. ! 7757: ** ! 7758: ** This function is called after sqlite3_expert_analyze() to extract the ! 7759: ** results of the analysis. Each call to this function returns either a ! 7760: ** NULL pointer or a pointer to a buffer containing a nul-terminated string. ! 7761: ** The value passed as the third argument must be one of the EXPERT_REPORT_* ! 7762: ** #define constants defined below. ! 7763: ** ! 7764: ** For some EXPERT_REPORT_* parameters, the buffer returned contains ! 7765: ** information relating to a specific SQL statement. In these cases that ! 7766: ** SQL statement is identified by the value passed as the second argument. ! 7767: ** SQL statements are numbered from 0 in the order in which they are parsed. ! 7768: ** If an out-of-range value (less than zero or equal to or greater than the ! 7769: ** value returned by sqlite3_expert_count()) is passed as the second argument ! 7770: ** along with such an EXPERT_REPORT_* parameter, NULL is always returned. ! 7771: ** ! 7772: ** EXPERT_REPORT_SQL: ! 7773: ** Return the text of SQL statement iStmt. ! 7774: ** ! 7775: ** EXPERT_REPORT_INDEXES: ! 7776: ** Return a buffer containing the CREATE INDEX statements for all recommended ! 7777: ** indexes for statement iStmt. If there are no new recommeded indexes, NULL ! 7778: ** is returned. ! 7779: ** ! 7780: ** EXPERT_REPORT_PLAN: ! 7781: ** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query ! 7782: ** iStmt after the proposed indexes have been added to the database schema. ! 7783: ** ! 7784: ** EXPERT_REPORT_CANDIDATES: ! 7785: ** Return a pointer to a buffer containing the CREATE INDEX statements ! 7786: ** for all indexes that were tested (for all SQL statements). The iStmt ! 7787: ** parameter is ignored for EXPERT_REPORT_CANDIDATES calls. ! 7788: */ ! 7789: const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport); ! 7790: ! 7791: /* ! 7792: ** Values for the third argument passed to sqlite3_expert_report(). ! 7793: */ ! 7794: #define EXPERT_REPORT_SQL 1 ! 7795: #define EXPERT_REPORT_INDEXES 2 ! 7796: #define EXPERT_REPORT_PLAN 3 ! 7797: #define EXPERT_REPORT_CANDIDATES 4 ! 7798: ! 7799: /* ! 7800: ** Free an (sqlite3expert*) handle and all associated resources. There ! 7801: ** should be one call to this function for each successful call to ! 7802: ** sqlite3-expert_new(). ! 7803: */ ! 7804: void sqlite3_expert_destroy(sqlite3expert*); ! 7805: ! 7806: #endif /* !defined(SQLITEEXPERT_H) */ ! 7807: ! 7808: /************************* End ../ext/expert/sqlite3expert.h ********************/ ! 7809: /************************* Begin ../ext/expert/sqlite3expert.c ******************/ ! 7810: /* ! 7811: ** 2017 April 09 ! 7812: ** ! 7813: ** The author disclaims copyright to this source code. In place of ! 7814: ** a legal notice, here is a blessing: ! 7815: ** ! 7816: ** May you do good and not evil. ! 7817: ** May you find forgiveness for yourself and forgive others. ! 7818: ** May you share freely, never taking more than you give. ! 7819: ** ! 7820: ************************************************************************* ! 7821: */ ! 7822: /* #include "sqlite3expert.h" */ ! 7823: #include <assert.h> ! 7824: #include <string.h> ! 7825: #include <stdio.h> ! 7826: ! 7827: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 7828: ! 7829: /* typedef sqlite3_int64 i64; */ ! 7830: /* typedef sqlite3_uint64 u64; */ ! 7831: ! 7832: typedef struct IdxColumn IdxColumn; ! 7833: typedef struct IdxConstraint IdxConstraint; ! 7834: typedef struct IdxScan IdxScan; ! 7835: typedef struct IdxStatement IdxStatement; ! 7836: typedef struct IdxTable IdxTable; ! 7837: typedef struct IdxWrite IdxWrite; ! 7838: ! 7839: #define STRLEN (int)strlen ! 7840: ! 7841: /* ! 7842: ** A temp table name that we assume no user database will actually use. ! 7843: ** If this assumption proves incorrect triggers on the table with the ! 7844: ** conflicting name will be ignored. ! 7845: */ ! 7846: #define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776" ! 7847: ! 7848: /* ! 7849: ** A single constraint. Equivalent to either "col = ?" or "col < ?" (or ! 7850: ** any other type of single-ended range constraint on a column). ! 7851: ** ! 7852: ** pLink: ! 7853: ** Used to temporarily link IdxConstraint objects into lists while ! 7854: ** creating candidate indexes. ! 7855: */ ! 7856: struct IdxConstraint { ! 7857: char *zColl; /* Collation sequence */ ! 7858: int bRange; /* True for range, false for eq */ ! 7859: int iCol; /* Constrained table column */ ! 7860: int bFlag; /* Used by idxFindCompatible() */ ! 7861: int bDesc; /* True if ORDER BY <expr> DESC */ ! 7862: IdxConstraint *pNext; /* Next constraint in pEq or pRange list */ ! 7863: IdxConstraint *pLink; /* See above */ ! 7864: }; ! 7865: ! 7866: /* ! 7867: ** A single scan of a single table. ! 7868: */ ! 7869: struct IdxScan { ! 7870: IdxTable *pTab; /* Associated table object */ ! 7871: int iDb; /* Database containing table zTable */ ! 7872: i64 covering; /* Mask of columns required for cov. index */ ! 7873: IdxConstraint *pOrder; /* ORDER BY columns */ ! 7874: IdxConstraint *pEq; /* List of == constraints */ ! 7875: IdxConstraint *pRange; /* List of < constraints */ ! 7876: IdxScan *pNextScan; /* Next IdxScan object for same analysis */ ! 7877: }; ! 7878: ! 7879: /* ! 7880: ** Information regarding a single database table. Extracted from ! 7881: ** "PRAGMA table_info" by function idxGetTableInfo(). ! 7882: */ ! 7883: struct IdxColumn { ! 7884: char *zName; ! 7885: char *zColl; ! 7886: int iPk; ! 7887: }; ! 7888: struct IdxTable { ! 7889: int nCol; ! 7890: char *zName; /* Table name */ ! 7891: IdxColumn *aCol; ! 7892: IdxTable *pNext; /* Next table in linked list of all tables */ ! 7893: }; ! 7894: ! 7895: /* ! 7896: ** An object of the following type is created for each unique table/write-op ! 7897: ** seen. The objects are stored in a singly-linked list beginning at ! 7898: ** sqlite3expert.pWrite. ! 7899: */ ! 7900: struct IdxWrite { ! 7901: IdxTable *pTab; ! 7902: int eOp; /* SQLITE_UPDATE, DELETE or INSERT */ ! 7903: IdxWrite *pNext; ! 7904: }; ! 7905: ! 7906: /* ! 7907: ** Each statement being analyzed is represented by an instance of this ! 7908: ** structure. ! 7909: */ ! 7910: struct IdxStatement { ! 7911: int iId; /* Statement number */ ! 7912: char *zSql; /* SQL statement */ ! 7913: char *zIdx; /* Indexes */ ! 7914: char *zEQP; /* Plan */ ! 7915: IdxStatement *pNext; ! 7916: }; ! 7917: ! 7918: ! 7919: /* ! 7920: ** A hash table for storing strings. With space for a payload string ! 7921: ** with each entry. Methods are: ! 7922: ** ! 7923: ** idxHashInit() ! 7924: ** idxHashClear() ! 7925: ** idxHashAdd() ! 7926: ** idxHashSearch() ! 7927: */ ! 7928: #define IDX_HASH_SIZE 1023 ! 7929: typedef struct IdxHashEntry IdxHashEntry; ! 7930: typedef struct IdxHash IdxHash; ! 7931: struct IdxHashEntry { ! 7932: char *zKey; /* nul-terminated key */ ! 7933: char *zVal; /* nul-terminated value string */ ! 7934: char *zVal2; /* nul-terminated value string 2 */ ! 7935: IdxHashEntry *pHashNext; /* Next entry in same hash bucket */ ! 7936: IdxHashEntry *pNext; /* Next entry in hash */ ! 7937: }; ! 7938: struct IdxHash { ! 7939: IdxHashEntry *pFirst; ! 7940: IdxHashEntry *aHash[IDX_HASH_SIZE]; ! 7941: }; ! 7942: ! 7943: /* ! 7944: ** sqlite3expert object. ! 7945: */ ! 7946: struct sqlite3expert { ! 7947: int iSample; /* Percentage of tables to sample for stat1 */ ! 7948: sqlite3 *db; /* User database */ ! 7949: sqlite3 *dbm; /* In-memory db for this analysis */ ! 7950: sqlite3 *dbv; /* Vtab schema for this analysis */ ! 7951: IdxTable *pTable; /* List of all IdxTable objects */ ! 7952: IdxScan *pScan; /* List of scan objects */ ! 7953: IdxWrite *pWrite; /* List of write objects */ ! 7954: IdxStatement *pStatement; /* List of IdxStatement objects */ ! 7955: int bRun; /* True once analysis has run */ ! 7956: char **pzErrmsg; ! 7957: int rc; /* Error code from whereinfo hook */ ! 7958: IdxHash hIdx; /* Hash containing all candidate indexes */ ! 7959: char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */ ! 7960: }; ! 7961: ! 7962: ! 7963: /* ! 7964: ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). ! 7965: ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. ! 7966: */ ! 7967: static void *idxMalloc(int *pRc, int nByte){ ! 7968: void *pRet; ! 7969: assert( *pRc==SQLITE_OK ); ! 7970: assert( nByte>0 ); ! 7971: pRet = sqlite3_malloc(nByte); ! 7972: if( pRet ){ ! 7973: memset(pRet, 0, nByte); ! 7974: }else{ ! 7975: *pRc = SQLITE_NOMEM; ! 7976: } ! 7977: return pRet; ! 7978: } ! 7979: ! 7980: /* ! 7981: ** Initialize an IdxHash hash table. ! 7982: */ ! 7983: static void idxHashInit(IdxHash *pHash){ ! 7984: memset(pHash, 0, sizeof(IdxHash)); ! 7985: } ! 7986: ! 7987: /* ! 7988: ** Reset an IdxHash hash table. ! 7989: */ ! 7990: static void idxHashClear(IdxHash *pHash){ ! 7991: int i; ! 7992: for(i=0; i<IDX_HASH_SIZE; i++){ ! 7993: IdxHashEntry *pEntry; ! 7994: IdxHashEntry *pNext; ! 7995: for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){ ! 7996: pNext = pEntry->pHashNext; ! 7997: sqlite3_free(pEntry->zVal2); ! 7998: sqlite3_free(pEntry); ! 7999: } ! 8000: } ! 8001: memset(pHash, 0, sizeof(IdxHash)); ! 8002: } ! 8003: ! 8004: /* ! 8005: ** Return the index of the hash bucket that the string specified by the ! 8006: ** arguments to this function belongs. ! 8007: */ ! 8008: static int idxHashString(const char *z, int n){ ! 8009: unsigned int ret = 0; ! 8010: int i; ! 8011: for(i=0; i<n; i++){ ! 8012: ret += (ret<<3) + (unsigned char)(z[i]); ! 8013: } ! 8014: return (int)(ret % IDX_HASH_SIZE); ! 8015: } ! 8016: ! 8017: /* ! 8018: ** If zKey is already present in the hash table, return non-zero and do ! 8019: ** nothing. Otherwise, add an entry with key zKey and payload string zVal to ! 8020: ** the hash table passed as the second argument. ! 8021: */ ! 8022: static int idxHashAdd( ! 8023: int *pRc, ! 8024: IdxHash *pHash, ! 8025: const char *zKey, ! 8026: const char *zVal ! 8027: ){ ! 8028: int nKey = STRLEN(zKey); ! 8029: int iHash = idxHashString(zKey, nKey); ! 8030: int nVal = (zVal ? STRLEN(zVal) : 0); ! 8031: IdxHashEntry *pEntry; ! 8032: assert( iHash>=0 ); ! 8033: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ ! 8034: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ ! 8035: return 1; ! 8036: } ! 8037: } ! 8038: pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); ! 8039: if( pEntry ){ ! 8040: pEntry->zKey = (char*)&pEntry[1]; ! 8041: memcpy(pEntry->zKey, zKey, nKey); ! 8042: if( zVal ){ ! 8043: pEntry->zVal = &pEntry->zKey[nKey+1]; ! 8044: memcpy(pEntry->zVal, zVal, nVal); ! 8045: } ! 8046: pEntry->pHashNext = pHash->aHash[iHash]; ! 8047: pHash->aHash[iHash] = pEntry; ! 8048: ! 8049: pEntry->pNext = pHash->pFirst; ! 8050: pHash->pFirst = pEntry; ! 8051: } ! 8052: return 0; ! 8053: } ! 8054: ! 8055: /* ! 8056: ** If zKey/nKey is present in the hash table, return a pointer to the ! 8057: ** hash-entry object. ! 8058: */ ! 8059: static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){ ! 8060: int iHash; ! 8061: IdxHashEntry *pEntry; ! 8062: if( nKey<0 ) nKey = STRLEN(zKey); ! 8063: iHash = idxHashString(zKey, nKey); ! 8064: assert( iHash>=0 ); ! 8065: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ ! 8066: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ ! 8067: return pEntry; ! 8068: } ! 8069: } ! 8070: return 0; ! 8071: } ! 8072: ! 8073: /* ! 8074: ** If the hash table contains an entry with a key equal to the string ! 8075: ** passed as the final two arguments to this function, return a pointer ! 8076: ** to the payload string. Otherwise, if zKey/nKey is not present in the ! 8077: ** hash table, return NULL. ! 8078: */ ! 8079: static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){ ! 8080: IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey); ! 8081: if( pEntry ) return pEntry->zVal; ! 8082: return 0; ! 8083: } ! 8084: ! 8085: /* ! 8086: ** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl ! 8087: ** variable to point to a copy of nul-terminated string zColl. ! 8088: */ ! 8089: static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){ ! 8090: IdxConstraint *pNew; ! 8091: int nColl = STRLEN(zColl); ! 8092: ! 8093: assert( *pRc==SQLITE_OK ); ! 8094: pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1); ! 8095: if( pNew ){ ! 8096: pNew->zColl = (char*)&pNew[1]; ! 8097: memcpy(pNew->zColl, zColl, nColl+1); ! 8098: } ! 8099: return pNew; ! 8100: } ! 8101: ! 8102: /* ! 8103: ** An error associated with database handle db has just occurred. Pass ! 8104: ** the error message to callback function xOut. ! 8105: */ ! 8106: static void idxDatabaseError( ! 8107: sqlite3 *db, /* Database handle */ ! 8108: char **pzErrmsg /* Write error here */ ! 8109: ){ ! 8110: *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ! 8111: } ! 8112: ! 8113: /* ! 8114: ** Prepare an SQL statement. ! 8115: */ ! 8116: static int idxPrepareStmt( ! 8117: sqlite3 *db, /* Database handle to compile against */ ! 8118: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ ! 8119: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ ! 8120: const char *zSql /* SQL statement to compile */ ! 8121: ){ ! 8122: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); ! 8123: if( rc!=SQLITE_OK ){ ! 8124: *ppStmt = 0; ! 8125: idxDatabaseError(db, pzErrmsg); ! 8126: } ! 8127: return rc; ! 8128: } ! 8129: ! 8130: /* ! 8131: ** Prepare an SQL statement using the results of a printf() formatting. ! 8132: */ ! 8133: static int idxPrintfPrepareStmt( ! 8134: sqlite3 *db, /* Database handle to compile against */ ! 8135: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ ! 8136: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ ! 8137: const char *zFmt, /* printf() format of SQL statement */ ! 8138: ... /* Trailing printf() arguments */ ! 8139: ){ ! 8140: va_list ap; ! 8141: int rc; ! 8142: char *zSql; ! 8143: va_start(ap, zFmt); ! 8144: zSql = sqlite3_vmprintf(zFmt, ap); ! 8145: if( zSql==0 ){ ! 8146: rc = SQLITE_NOMEM; ! 8147: }else{ ! 8148: rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql); ! 8149: sqlite3_free(zSql); ! 8150: } ! 8151: va_end(ap); ! 8152: return rc; ! 8153: } ! 8154: ! 8155: ! 8156: /************************************************************************* ! 8157: ** Beginning of virtual table implementation. ! 8158: */ ! 8159: typedef struct ExpertVtab ExpertVtab; ! 8160: struct ExpertVtab { ! 8161: sqlite3_vtab base; ! 8162: IdxTable *pTab; ! 8163: sqlite3expert *pExpert; ! 8164: }; ! 8165: ! 8166: typedef struct ExpertCsr ExpertCsr; ! 8167: struct ExpertCsr { ! 8168: sqlite3_vtab_cursor base; ! 8169: sqlite3_stmt *pData; ! 8170: }; ! 8171: ! 8172: static char *expertDequote(const char *zIn){ ! 8173: int n = STRLEN(zIn); ! 8174: char *zRet = sqlite3_malloc(n); ! 8175: ! 8176: assert( zIn[0]=='\'' ); ! 8177: assert( zIn[n-1]=='\'' ); ! 8178: ! 8179: if( zRet ){ ! 8180: int iOut = 0; ! 8181: int iIn = 0; ! 8182: for(iIn=1; iIn<(n-1); iIn++){ ! 8183: if( zIn[iIn]=='\'' ){ ! 8184: assert( zIn[iIn+1]=='\'' ); ! 8185: iIn++; ! 8186: } ! 8187: zRet[iOut++] = zIn[iIn]; ! 8188: } ! 8189: zRet[iOut] = '\0'; ! 8190: } ! 8191: ! 8192: return zRet; ! 8193: } ! 8194: ! 8195: /* ! 8196: ** This function is the implementation of both the xConnect and xCreate ! 8197: ** methods of the r-tree virtual table. ! 8198: ** ! 8199: ** argv[0] -> module name ! 8200: ** argv[1] -> database name ! 8201: ** argv[2] -> table name ! 8202: ** argv[...] -> column names... ! 8203: */ ! 8204: static int expertConnect( ! 8205: sqlite3 *db, ! 8206: void *pAux, ! 8207: int argc, const char *const*argv, ! 8208: sqlite3_vtab **ppVtab, ! 8209: char **pzErr ! 8210: ){ ! 8211: sqlite3expert *pExpert = (sqlite3expert*)pAux; ! 8212: ExpertVtab *p = 0; ! 8213: int rc; ! 8214: ! 8215: if( argc!=4 ){ ! 8216: *pzErr = sqlite3_mprintf("internal error!"); ! 8217: rc = SQLITE_ERROR; ! 8218: }else{ ! 8219: char *zCreateTable = expertDequote(argv[3]); ! 8220: if( zCreateTable ){ ! 8221: rc = sqlite3_declare_vtab(db, zCreateTable); ! 8222: if( rc==SQLITE_OK ){ ! 8223: p = idxMalloc(&rc, sizeof(ExpertVtab)); ! 8224: } ! 8225: if( rc==SQLITE_OK ){ ! 8226: p->pExpert = pExpert; ! 8227: p->pTab = pExpert->pTable; ! 8228: assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 ); ! 8229: } ! 8230: sqlite3_free(zCreateTable); ! 8231: }else{ ! 8232: rc = SQLITE_NOMEM; ! 8233: } ! 8234: } ! 8235: ! 8236: *ppVtab = (sqlite3_vtab*)p; ! 8237: return rc; ! 8238: } ! 8239: ! 8240: static int expertDisconnect(sqlite3_vtab *pVtab){ ! 8241: ExpertVtab *p = (ExpertVtab*)pVtab; ! 8242: sqlite3_free(p); ! 8243: return SQLITE_OK; ! 8244: } ! 8245: ! 8246: static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){ ! 8247: ExpertVtab *p = (ExpertVtab*)pVtab; ! 8248: int rc = SQLITE_OK; ! 8249: int n = 0; ! 8250: IdxScan *pScan; ! 8251: const int opmask = ! 8252: SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT | ! 8253: SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE | ! 8254: SQLITE_INDEX_CONSTRAINT_LE; ! 8255: ! 8256: pScan = idxMalloc(&rc, sizeof(IdxScan)); ! 8257: if( pScan ){ ! 8258: int i; ! 8259: ! 8260: /* Link the new scan object into the list */ ! 8261: pScan->pTab = p->pTab; ! 8262: pScan->pNextScan = p->pExpert->pScan; ! 8263: p->pExpert->pScan = pScan; ! 8264: ! 8265: /* Add the constraints to the IdxScan object */ ! 8266: for(i=0; i<pIdxInfo->nConstraint; i++){ ! 8267: struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; ! 8268: if( pCons->usable ! 8269: && pCons->iColumn>=0 ! 8270: && p->pTab->aCol[pCons->iColumn].iPk==0 ! 8271: && (pCons->op & opmask) ! 8272: ){ ! 8273: IdxConstraint *pNew; ! 8274: const char *zColl = sqlite3_vtab_collation(pIdxInfo, i); ! 8275: pNew = idxNewConstraint(&rc, zColl); ! 8276: if( pNew ){ ! 8277: pNew->iCol = pCons->iColumn; ! 8278: if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ! 8279: pNew->pNext = pScan->pEq; ! 8280: pScan->pEq = pNew; ! 8281: }else{ ! 8282: pNew->bRange = 1; ! 8283: pNew->pNext = pScan->pRange; ! 8284: pScan->pRange = pNew; ! 8285: } ! 8286: } ! 8287: n++; ! 8288: pIdxInfo->aConstraintUsage[i].argvIndex = n; ! 8289: } ! 8290: } ! 8291: ! 8292: /* Add the ORDER BY to the IdxScan object */ ! 8293: for(i=pIdxInfo->nOrderBy-1; i>=0; i--){ ! 8294: int iCol = pIdxInfo->aOrderBy[i].iColumn; ! 8295: if( iCol>=0 ){ ! 8296: IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl); ! 8297: if( pNew ){ ! 8298: pNew->iCol = iCol; ! 8299: pNew->bDesc = pIdxInfo->aOrderBy[i].desc; ! 8300: pNew->pNext = pScan->pOrder; ! 8301: pNew->pLink = pScan->pOrder; ! 8302: pScan->pOrder = pNew; ! 8303: n++; ! 8304: } ! 8305: } ! 8306: } ! 8307: } ! 8308: ! 8309: pIdxInfo->estimatedCost = 1000000.0 / (n+1); ! 8310: return rc; ! 8311: } ! 8312: ! 8313: static int expertUpdate( ! 8314: sqlite3_vtab *pVtab, ! 8315: int nData, ! 8316: sqlite3_value **azData, ! 8317: sqlite_int64 *pRowid ! 8318: ){ ! 8319: (void)pVtab; ! 8320: (void)nData; ! 8321: (void)azData; ! 8322: (void)pRowid; ! 8323: return SQLITE_OK; ! 8324: } ! 8325: ! 8326: /* ! 8327: ** Virtual table module xOpen method. ! 8328: */ ! 8329: static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ ! 8330: int rc = SQLITE_OK; ! 8331: ExpertCsr *pCsr; ! 8332: (void)pVTab; ! 8333: pCsr = idxMalloc(&rc, sizeof(ExpertCsr)); ! 8334: *ppCursor = (sqlite3_vtab_cursor*)pCsr; ! 8335: return rc; ! 8336: } ! 8337: ! 8338: /* ! 8339: ** Virtual table module xClose method. ! 8340: */ ! 8341: static int expertClose(sqlite3_vtab_cursor *cur){ ! 8342: ExpertCsr *pCsr = (ExpertCsr*)cur; ! 8343: sqlite3_finalize(pCsr->pData); ! 8344: sqlite3_free(pCsr); ! 8345: return SQLITE_OK; ! 8346: } ! 8347: ! 8348: /* ! 8349: ** Virtual table module xEof method. ! 8350: ** ! 8351: ** Return non-zero if the cursor does not currently point to a valid ! 8352: ** record (i.e if the scan has finished), or zero otherwise. ! 8353: */ ! 8354: static int expertEof(sqlite3_vtab_cursor *cur){ ! 8355: ExpertCsr *pCsr = (ExpertCsr*)cur; ! 8356: return pCsr->pData==0; ! 8357: } ! 8358: ! 8359: /* ! 8360: ** Virtual table module xNext method. ! 8361: */ ! 8362: static int expertNext(sqlite3_vtab_cursor *cur){ ! 8363: ExpertCsr *pCsr = (ExpertCsr*)cur; ! 8364: int rc = SQLITE_OK; ! 8365: ! 8366: assert( pCsr->pData ); ! 8367: rc = sqlite3_step(pCsr->pData); ! 8368: if( rc!=SQLITE_ROW ){ ! 8369: rc = sqlite3_finalize(pCsr->pData); ! 8370: pCsr->pData = 0; ! 8371: }else{ ! 8372: rc = SQLITE_OK; ! 8373: } ! 8374: ! 8375: return rc; ! 8376: } ! 8377: ! 8378: /* ! 8379: ** Virtual table module xRowid method. ! 8380: */ ! 8381: static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ! 8382: (void)cur; ! 8383: *pRowid = 0; ! 8384: return SQLITE_OK; ! 8385: } ! 8386: ! 8387: /* ! 8388: ** Virtual table module xColumn method. ! 8389: */ ! 8390: static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ ! 8391: ExpertCsr *pCsr = (ExpertCsr*)cur; ! 8392: sqlite3_value *pVal; ! 8393: pVal = sqlite3_column_value(pCsr->pData, i); ! 8394: if( pVal ){ ! 8395: sqlite3_result_value(ctx, pVal); ! 8396: } ! 8397: return SQLITE_OK; ! 8398: } ! 8399: ! 8400: /* ! 8401: ** Virtual table module xFilter method. ! 8402: */ ! 8403: static int expertFilter( ! 8404: sqlite3_vtab_cursor *cur, ! 8405: int idxNum, const char *idxStr, ! 8406: int argc, sqlite3_value **argv ! 8407: ){ ! 8408: ExpertCsr *pCsr = (ExpertCsr*)cur; ! 8409: ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab); ! 8410: sqlite3expert *pExpert = pVtab->pExpert; ! 8411: int rc; ! 8412: ! 8413: (void)idxNum; ! 8414: (void)idxStr; ! 8415: (void)argc; ! 8416: (void)argv; ! 8417: rc = sqlite3_finalize(pCsr->pData); ! 8418: pCsr->pData = 0; ! 8419: if( rc==SQLITE_OK ){ ! 8420: rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg, ! 8421: "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName ! 8422: ); ! 8423: } ! 8424: ! 8425: if( rc==SQLITE_OK ){ ! 8426: rc = expertNext(cur); ! 8427: } ! 8428: return rc; ! 8429: } ! 8430: ! 8431: static int idxRegisterVtab(sqlite3expert *p){ ! 8432: static sqlite3_module expertModule = { ! 8433: 2, /* iVersion */ ! 8434: expertConnect, /* xCreate - create a table */ ! 8435: expertConnect, /* xConnect - connect to an existing table */ ! 8436: expertBestIndex, /* xBestIndex - Determine search strategy */ ! 8437: expertDisconnect, /* xDisconnect - Disconnect from a table */ ! 8438: expertDisconnect, /* xDestroy - Drop a table */ ! 8439: expertOpen, /* xOpen - open a cursor */ ! 8440: expertClose, /* xClose - close a cursor */ ! 8441: expertFilter, /* xFilter - configure scan constraints */ ! 8442: expertNext, /* xNext - advance a cursor */ ! 8443: expertEof, /* xEof */ ! 8444: expertColumn, /* xColumn - read data */ ! 8445: expertRowid, /* xRowid - read data */ ! 8446: expertUpdate, /* xUpdate - write data */ ! 8447: 0, /* xBegin - begin transaction */ ! 8448: 0, /* xSync - sync transaction */ ! 8449: 0, /* xCommit - commit transaction */ ! 8450: 0, /* xRollback - rollback transaction */ ! 8451: 0, /* xFindFunction - function overloading */ ! 8452: 0, /* xRename - rename the table */ ! 8453: 0, /* xSavepoint */ ! 8454: 0, /* xRelease */ ! 8455: 0, /* xRollbackTo */ ! 8456: 0, /* xShadowName */ ! 8457: }; ! 8458: ! 8459: return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); ! 8460: } ! 8461: /* ! 8462: ** End of virtual table implementation. ! 8463: *************************************************************************/ ! 8464: /* ! 8465: ** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function ! 8466: ** is called, set it to the return value of sqlite3_finalize() before ! 8467: ** returning. Otherwise, discard the sqlite3_finalize() return value. ! 8468: */ ! 8469: static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){ ! 8470: int rc = sqlite3_finalize(pStmt); ! 8471: if( *pRc==SQLITE_OK ) *pRc = rc; ! 8472: } ! 8473: ! 8474: /* ! 8475: ** Attempt to allocate an IdxTable structure corresponding to table zTab ! 8476: ** in the main database of connection db. If successful, set (*ppOut) to ! 8477: ** point to the new object and return SQLITE_OK. Otherwise, return an ! 8478: ** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be ! 8479: ** set to point to an error string. ! 8480: ** ! 8481: ** It is the responsibility of the caller to eventually free either the ! 8482: ** IdxTable object or error message using sqlite3_free(). ! 8483: */ ! 8484: static int idxGetTableInfo( ! 8485: sqlite3 *db, /* Database connection to read details from */ ! 8486: const char *zTab, /* Table name */ ! 8487: IdxTable **ppOut, /* OUT: New object (if successful) */ ! 8488: char **pzErrmsg /* OUT: Error message (if not) */ ! 8489: ){ ! 8490: sqlite3_stmt *p1 = 0; ! 8491: int nCol = 0; ! 8492: int nTab = STRLEN(zTab); ! 8493: int nByte = sizeof(IdxTable) + nTab + 1; ! 8494: IdxTable *pNew = 0; ! 8495: int rc, rc2; ! 8496: char *pCsr = 0; ! 8497: ! 8498: rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab); ! 8499: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ ! 8500: const char *zCol = (const char*)sqlite3_column_text(p1, 1); ! 8501: nByte += 1 + STRLEN(zCol); ! 8502: rc = sqlite3_table_column_metadata( ! 8503: db, "main", zTab, zCol, 0, &zCol, 0, 0, 0 ! 8504: ); ! 8505: nByte += 1 + STRLEN(zCol); ! 8506: nCol++; ! 8507: } ! 8508: rc2 = sqlite3_reset(p1); ! 8509: if( rc==SQLITE_OK ) rc = rc2; ! 8510: ! 8511: nByte += sizeof(IdxColumn) * nCol; ! 8512: if( rc==SQLITE_OK ){ ! 8513: pNew = idxMalloc(&rc, nByte); ! 8514: } ! 8515: if( rc==SQLITE_OK ){ ! 8516: pNew->aCol = (IdxColumn*)&pNew[1]; ! 8517: pNew->nCol = nCol; ! 8518: pCsr = (char*)&pNew->aCol[nCol]; ! 8519: } ! 8520: ! 8521: nCol = 0; ! 8522: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ ! 8523: const char *zCol = (const char*)sqlite3_column_text(p1, 1); ! 8524: int nCopy = STRLEN(zCol) + 1; ! 8525: pNew->aCol[nCol].zName = pCsr; ! 8526: pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5); ! 8527: memcpy(pCsr, zCol, nCopy); ! 8528: pCsr += nCopy; ! 8529: ! 8530: rc = sqlite3_table_column_metadata( ! 8531: db, "main", zTab, zCol, 0, &zCol, 0, 0, 0 ! 8532: ); ! 8533: if( rc==SQLITE_OK ){ ! 8534: nCopy = STRLEN(zCol) + 1; ! 8535: pNew->aCol[nCol].zColl = pCsr; ! 8536: memcpy(pCsr, zCol, nCopy); ! 8537: pCsr += nCopy; ! 8538: } ! 8539: ! 8540: nCol++; ! 8541: } ! 8542: idxFinalize(&rc, p1); ! 8543: ! 8544: if( rc!=SQLITE_OK ){ ! 8545: sqlite3_free(pNew); ! 8546: pNew = 0; ! 8547: }else{ ! 8548: pNew->zName = pCsr; ! 8549: memcpy(pNew->zName, zTab, nTab+1); ! 8550: } ! 8551: ! 8552: *ppOut = pNew; ! 8553: return rc; ! 8554: } ! 8555: ! 8556: /* ! 8557: ** This function is a no-op if *pRc is set to anything other than ! 8558: ** SQLITE_OK when it is called. ! 8559: ** ! 8560: ** If *pRc is initially set to SQLITE_OK, then the text specified by ! 8561: ** the printf() style arguments is appended to zIn and the result returned ! 8562: ** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on ! 8563: ** zIn before returning. ! 8564: */ ! 8565: static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ ! 8566: va_list ap; ! 8567: char *zAppend = 0; ! 8568: char *zRet = 0; ! 8569: int nIn = zIn ? STRLEN(zIn) : 0; ! 8570: int nAppend = 0; ! 8571: va_start(ap, zFmt); ! 8572: if( *pRc==SQLITE_OK ){ ! 8573: zAppend = sqlite3_vmprintf(zFmt, ap); ! 8574: if( zAppend ){ ! 8575: nAppend = STRLEN(zAppend); ! 8576: zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); ! 8577: } ! 8578: if( zAppend && zRet ){ ! 8579: if( nIn ) memcpy(zRet, zIn, nIn); ! 8580: memcpy(&zRet[nIn], zAppend, nAppend+1); ! 8581: }else{ ! 8582: sqlite3_free(zRet); ! 8583: zRet = 0; ! 8584: *pRc = SQLITE_NOMEM; ! 8585: } ! 8586: sqlite3_free(zAppend); ! 8587: sqlite3_free(zIn); ! 8588: } ! 8589: va_end(ap); ! 8590: return zRet; ! 8591: } ! 8592: ! 8593: /* ! 8594: ** Return true if zId must be quoted in order to use it as an SQL ! 8595: ** identifier, or false otherwise. ! 8596: */ ! 8597: static int idxIdentifierRequiresQuotes(const char *zId){ ! 8598: int i; ! 8599: for(i=0; zId[i]; i++){ ! 8600: if( !(zId[i]=='_') ! 8601: && !(zId[i]>='0' && zId[i]<='9') ! 8602: && !(zId[i]>='a' && zId[i]<='z') ! 8603: && !(zId[i]>='A' && zId[i]<='Z') ! 8604: ){ ! 8605: return 1; ! 8606: } ! 8607: } ! 8608: return 0; ! 8609: } ! 8610: ! 8611: /* ! 8612: ** This function appends an index column definition suitable for constraint ! 8613: ** pCons to the string passed as zIn and returns the result. ! 8614: */ ! 8615: static char *idxAppendColDefn( ! 8616: int *pRc, /* IN/OUT: Error code */ ! 8617: char *zIn, /* Column defn accumulated so far */ ! 8618: IdxTable *pTab, /* Table index will be created on */ ! 8619: IdxConstraint *pCons ! 8620: ){ ! 8621: char *zRet = zIn; ! 8622: IdxColumn *p = &pTab->aCol[pCons->iCol]; ! 8623: if( zRet ) zRet = idxAppendText(pRc, zRet, ", "); ! 8624: ! 8625: if( idxIdentifierRequiresQuotes(p->zName) ){ ! 8626: zRet = idxAppendText(pRc, zRet, "%Q", p->zName); ! 8627: }else{ ! 8628: zRet = idxAppendText(pRc, zRet, "%s", p->zName); ! 8629: } ! 8630: ! 8631: if( sqlite3_stricmp(p->zColl, pCons->zColl) ){ ! 8632: if( idxIdentifierRequiresQuotes(pCons->zColl) ){ ! 8633: zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl); ! 8634: }else{ ! 8635: zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl); ! 8636: } ! 8637: } ! 8638: ! 8639: if( pCons->bDesc ){ ! 8640: zRet = idxAppendText(pRc, zRet, " DESC"); ! 8641: } ! 8642: return zRet; ! 8643: } ! 8644: ! 8645: /* ! 8646: ** Search database dbm for an index compatible with the one idxCreateFromCons() ! 8647: ** would create from arguments pScan, pEq and pTail. If no error occurs and ! 8648: ** such an index is found, return non-zero. Or, if no such index is found, ! 8649: ** return zero. ! 8650: ** ! 8651: ** If an error occurs, set *pRc to an SQLite error code and return zero. ! 8652: */ ! 8653: static int idxFindCompatible( ! 8654: int *pRc, /* OUT: Error code */ ! 8655: sqlite3* dbm, /* Database to search */ ! 8656: IdxScan *pScan, /* Scan for table to search for index on */ ! 8657: IdxConstraint *pEq, /* List of == constraints */ ! 8658: IdxConstraint *pTail /* List of range constraints */ ! 8659: ){ ! 8660: const char *zTbl = pScan->pTab->zName; ! 8661: sqlite3_stmt *pIdxList = 0; ! 8662: IdxConstraint *pIter; ! 8663: int nEq = 0; /* Number of elements in pEq */ ! 8664: int rc; ! 8665: ! 8666: /* Count the elements in list pEq */ ! 8667: for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++; ! 8668: ! 8669: rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl); ! 8670: while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){ ! 8671: int bMatch = 1; ! 8672: IdxConstraint *pT = pTail; ! 8673: sqlite3_stmt *pInfo = 0; ! 8674: const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1); ! 8675: ! 8676: /* Zero the IdxConstraint.bFlag values in the pEq list */ ! 8677: for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0; ! 8678: ! 8679: rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx); ! 8680: while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){ ! 8681: int iIdx = sqlite3_column_int(pInfo, 0); ! 8682: int iCol = sqlite3_column_int(pInfo, 1); ! 8683: const char *zColl = (const char*)sqlite3_column_text(pInfo, 4); ! 8684: ! 8685: if( iIdx<nEq ){ ! 8686: for(pIter=pEq; pIter; pIter=pIter->pLink){ ! 8687: if( pIter->bFlag ) continue; ! 8688: if( pIter->iCol!=iCol ) continue; ! 8689: if( sqlite3_stricmp(pIter->zColl, zColl) ) continue; ! 8690: pIter->bFlag = 1; ! 8691: break; ! 8692: } ! 8693: if( pIter==0 ){ ! 8694: bMatch = 0; ! 8695: break; ! 8696: } ! 8697: }else{ ! 8698: if( pT ){ ! 8699: if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){ ! 8700: bMatch = 0; ! 8701: break; ! 8702: } ! 8703: pT = pT->pLink; ! 8704: } ! 8705: } ! 8706: } ! 8707: idxFinalize(&rc, pInfo); ! 8708: ! 8709: if( rc==SQLITE_OK && bMatch ){ ! 8710: sqlite3_finalize(pIdxList); ! 8711: return 1; ! 8712: } ! 8713: } ! 8714: idxFinalize(&rc, pIdxList); ! 8715: ! 8716: *pRc = rc; ! 8717: return 0; ! 8718: } ! 8719: ! 8720: static int idxCreateFromCons( ! 8721: sqlite3expert *p, ! 8722: IdxScan *pScan, ! 8723: IdxConstraint *pEq, ! 8724: IdxConstraint *pTail ! 8725: ){ ! 8726: sqlite3 *dbm = p->dbm; ! 8727: int rc = SQLITE_OK; ! 8728: if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ ! 8729: IdxTable *pTab = pScan->pTab; ! 8730: char *zCols = 0; ! 8731: char *zIdx = 0; ! 8732: IdxConstraint *pCons; ! 8733: unsigned int h = 0; ! 8734: const char *zFmt; ! 8735: ! 8736: for(pCons=pEq; pCons; pCons=pCons->pLink){ ! 8737: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); ! 8738: } ! 8739: for(pCons=pTail; pCons; pCons=pCons->pLink){ ! 8740: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); ! 8741: } ! 8742: ! 8743: if( rc==SQLITE_OK ){ ! 8744: /* Hash the list of columns to come up with a name for the index */ ! 8745: const char *zTable = pScan->pTab->zName; ! 8746: char *zName; /* Index name */ ! 8747: int i; ! 8748: for(i=0; zCols[i]; i++){ ! 8749: h += ((h<<3) + zCols[i]); ! 8750: } ! 8751: zName = sqlite3_mprintf("%s_idx_%08x", zTable, h); ! 8752: if( zName==0 ){ ! 8753: rc = SQLITE_NOMEM; ! 8754: }else{ ! 8755: if( idxIdentifierRequiresQuotes(zTable) ){ ! 8756: zFmt = "CREATE INDEX '%q' ON %Q(%s)"; ! 8757: }else{ ! 8758: zFmt = "CREATE INDEX %s ON %s(%s)"; ! 8759: } ! 8760: zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols); ! 8761: if( !zIdx ){ ! 8762: rc = SQLITE_NOMEM; ! 8763: }else{ ! 8764: rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg); ! 8765: idxHashAdd(&rc, &p->hIdx, zName, zIdx); ! 8766: } ! 8767: sqlite3_free(zName); ! 8768: sqlite3_free(zIdx); ! 8769: } ! 8770: } ! 8771: ! 8772: sqlite3_free(zCols); ! 8773: } ! 8774: return rc; ! 8775: } ! 8776: ! 8777: /* ! 8778: ** Return true if list pList (linked by IdxConstraint.pLink) contains ! 8779: ** a constraint compatible with *p. Otherwise return false. ! 8780: */ ! 8781: static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){ ! 8782: IdxConstraint *pCmp; ! 8783: for(pCmp=pList; pCmp; pCmp=pCmp->pLink){ ! 8784: if( p->iCol==pCmp->iCol ) return 1; ! 8785: } ! 8786: return 0; ! 8787: } ! 8788: ! 8789: static int idxCreateFromWhere( ! 8790: sqlite3expert *p, ! 8791: IdxScan *pScan, /* Create indexes for this scan */ ! 8792: IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ ! 8793: ){ ! 8794: IdxConstraint *p1 = 0; ! 8795: IdxConstraint *pCon; ! 8796: int rc; ! 8797: ! 8798: /* Gather up all the == constraints. */ ! 8799: for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){ ! 8800: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ ! 8801: pCon->pLink = p1; ! 8802: p1 = pCon; ! 8803: } ! 8804: } ! 8805: ! 8806: /* Create an index using the == constraints collected above. And the ! 8807: ** range constraint/ORDER BY terms passed in by the caller, if any. */ ! 8808: rc = idxCreateFromCons(p, pScan, p1, pTail); ! 8809: ! 8810: /* If no range/ORDER BY passed by the caller, create a version of the ! 8811: ** index for each range constraint. */ ! 8812: if( pTail==0 ){ ! 8813: for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){ ! 8814: assert( pCon->pLink==0 ); ! 8815: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ ! 8816: rc = idxCreateFromCons(p, pScan, p1, pCon); ! 8817: } ! 8818: } ! 8819: } ! 8820: ! 8821: return rc; ! 8822: } ! 8823: ! 8824: /* ! 8825: ** Create candidate indexes in database [dbm] based on the data in ! 8826: ** linked-list pScan. ! 8827: */ ! 8828: static int idxCreateCandidates(sqlite3expert *p){ ! 8829: int rc = SQLITE_OK; ! 8830: IdxScan *pIter; ! 8831: ! 8832: for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ ! 8833: rc = idxCreateFromWhere(p, pIter, 0); ! 8834: if( rc==SQLITE_OK && pIter->pOrder ){ ! 8835: rc = idxCreateFromWhere(p, pIter, pIter->pOrder); ! 8836: } ! 8837: } ! 8838: ! 8839: return rc; ! 8840: } ! 8841: ! 8842: /* ! 8843: ** Free all elements of the linked list starting at pConstraint. ! 8844: */ ! 8845: static void idxConstraintFree(IdxConstraint *pConstraint){ ! 8846: IdxConstraint *pNext; ! 8847: IdxConstraint *p; ! 8848: ! 8849: for(p=pConstraint; p; p=pNext){ ! 8850: pNext = p->pNext; ! 8851: sqlite3_free(p); ! 8852: } ! 8853: } ! 8854: ! 8855: /* ! 8856: ** Free all elements of the linked list starting from pScan up until pLast ! 8857: ** (pLast is not freed). ! 8858: */ ! 8859: static void idxScanFree(IdxScan *pScan, IdxScan *pLast){ ! 8860: IdxScan *p; ! 8861: IdxScan *pNext; ! 8862: for(p=pScan; p!=pLast; p=pNext){ ! 8863: pNext = p->pNextScan; ! 8864: idxConstraintFree(p->pOrder); ! 8865: idxConstraintFree(p->pEq); ! 8866: idxConstraintFree(p->pRange); ! 8867: sqlite3_free(p); ! 8868: } ! 8869: } ! 8870: ! 8871: /* ! 8872: ** Free all elements of the linked list starting from pStatement up ! 8873: ** until pLast (pLast is not freed). ! 8874: */ ! 8875: static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){ ! 8876: IdxStatement *p; ! 8877: IdxStatement *pNext; ! 8878: for(p=pStatement; p!=pLast; p=pNext){ ! 8879: pNext = p->pNext; ! 8880: sqlite3_free(p->zEQP); ! 8881: sqlite3_free(p->zIdx); ! 8882: sqlite3_free(p); ! 8883: } ! 8884: } ! 8885: ! 8886: /* ! 8887: ** Free the linked list of IdxTable objects starting at pTab. ! 8888: */ ! 8889: static void idxTableFree(IdxTable *pTab){ ! 8890: IdxTable *pIter; ! 8891: IdxTable *pNext; ! 8892: for(pIter=pTab; pIter; pIter=pNext){ ! 8893: pNext = pIter->pNext; ! 8894: sqlite3_free(pIter); ! 8895: } ! 8896: } ! 8897: ! 8898: /* ! 8899: ** Free the linked list of IdxWrite objects starting at pTab. ! 8900: */ ! 8901: static void idxWriteFree(IdxWrite *pTab){ ! 8902: IdxWrite *pIter; ! 8903: IdxWrite *pNext; ! 8904: for(pIter=pTab; pIter; pIter=pNext){ ! 8905: pNext = pIter->pNext; ! 8906: sqlite3_free(pIter); ! 8907: } ! 8908: } ! 8909: ! 8910: ! 8911: ! 8912: /* ! 8913: ** This function is called after candidate indexes have been created. It ! 8914: ** runs all the queries to see which indexes they prefer, and populates ! 8915: ** IdxStatement.zIdx and IdxStatement.zEQP with the results. ! 8916: */ ! 8917: int idxFindIndexes( ! 8918: sqlite3expert *p, ! 8919: char **pzErr /* OUT: Error message (sqlite3_malloc) */ ! 8920: ){ ! 8921: IdxStatement *pStmt; ! 8922: sqlite3 *dbm = p->dbm; ! 8923: int rc = SQLITE_OK; ! 8924: ! 8925: IdxHash hIdx; ! 8926: idxHashInit(&hIdx); ! 8927: ! 8928: for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){ ! 8929: IdxHashEntry *pEntry; ! 8930: sqlite3_stmt *pExplain = 0; ! 8931: idxHashClear(&hIdx); ! 8932: rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr, ! 8933: "EXPLAIN QUERY PLAN %s", pStmt->zSql ! 8934: ); ! 8935: while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ ! 8936: /* int iId = sqlite3_column_int(pExplain, 0); */ ! 8937: /* int iParent = sqlite3_column_int(pExplain, 1); */ ! 8938: /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ ! 8939: const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); ! 8940: int nDetail; ! 8941: int i; ! 8942: ! 8943: if( !zDetail ) continue; ! 8944: nDetail = STRLEN(zDetail); ! 8945: ! 8946: for(i=0; i<nDetail; i++){ ! 8947: const char *zIdx = 0; ! 8948: if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){ ! 8949: zIdx = &zDetail[i+13]; ! 8950: }else if( i+22<nDetail ! 8951: && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ! 8952: ){ ! 8953: zIdx = &zDetail[i+22]; ! 8954: } ! 8955: if( zIdx ){ ! 8956: const char *zSql; ! 8957: int nIdx = 0; ! 8958: while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){ ! 8959: nIdx++; ! 8960: } ! 8961: zSql = idxHashSearch(&p->hIdx, zIdx, nIdx); ! 8962: if( zSql ){ ! 8963: idxHashAdd(&rc, &hIdx, zSql, 0); ! 8964: if( rc ) goto find_indexes_out; ! 8965: } ! 8966: break; ! 8967: } ! 8968: } ! 8969: ! 8970: if( zDetail[0]!='-' ){ ! 8971: pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); ! 8972: } ! 8973: } ! 8974: ! 8975: for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ ! 8976: pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey); ! 8977: } ! 8978: ! 8979: idxFinalize(&rc, pExplain); ! 8980: } ! 8981: ! 8982: find_indexes_out: ! 8983: idxHashClear(&hIdx); ! 8984: return rc; ! 8985: } ! 8986: ! 8987: static int idxAuthCallback( ! 8988: void *pCtx, ! 8989: int eOp, ! 8990: const char *z3, ! 8991: const char *z4, ! 8992: const char *zDb, ! 8993: const char *zTrigger ! 8994: ){ ! 8995: int rc = SQLITE_OK; ! 8996: (void)z4; ! 8997: (void)zTrigger; ! 8998: if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){ ! 8999: if( sqlite3_stricmp(zDb, "main")==0 ){ ! 9000: sqlite3expert *p = (sqlite3expert*)pCtx; ! 9001: IdxTable *pTab; ! 9002: for(pTab=p->pTable; pTab; pTab=pTab->pNext){ ! 9003: if( 0==sqlite3_stricmp(z3, pTab->zName) ) break; ! 9004: } ! 9005: if( pTab ){ ! 9006: IdxWrite *pWrite; ! 9007: for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){ ! 9008: if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break; ! 9009: } ! 9010: if( pWrite==0 ){ ! 9011: pWrite = idxMalloc(&rc, sizeof(IdxWrite)); ! 9012: if( rc==SQLITE_OK ){ ! 9013: pWrite->pTab = pTab; ! 9014: pWrite->eOp = eOp; ! 9015: pWrite->pNext = p->pWrite; ! 9016: p->pWrite = pWrite; ! 9017: } ! 9018: } ! 9019: } ! 9020: } ! 9021: } ! 9022: return rc; ! 9023: } ! 9024: ! 9025: static int idxProcessOneTrigger( ! 9026: sqlite3expert *p, ! 9027: IdxWrite *pWrite, ! 9028: char **pzErr ! 9029: ){ ! 9030: static const char *zInt = UNIQUE_TABLE_NAME; ! 9031: static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME; ! 9032: IdxTable *pTab = pWrite->pTab; ! 9033: const char *zTab = pTab->zName; ! 9034: const char *zSql = ! 9035: "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema " ! 9036: "WHERE tbl_name = %Q AND type IN ('table', 'trigger') " ! 9037: "ORDER BY type;"; ! 9038: sqlite3_stmt *pSelect = 0; ! 9039: int rc = SQLITE_OK; ! 9040: char *zWrite = 0; ! 9041: ! 9042: /* Create the table and its triggers in the temp schema */ ! 9043: rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab); ! 9044: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){ ! 9045: const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0); ! 9046: rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr); ! 9047: } ! 9048: idxFinalize(&rc, pSelect); ! 9049: ! 9050: /* Rename the table in the temp schema to zInt */ ! 9051: if( rc==SQLITE_OK ){ ! 9052: char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt); ! 9053: if( z==0 ){ ! 9054: rc = SQLITE_NOMEM; ! 9055: }else{ ! 9056: rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr); ! 9057: sqlite3_free(z); ! 9058: } ! 9059: } ! 9060: ! 9061: switch( pWrite->eOp ){ ! 9062: case SQLITE_INSERT: { ! 9063: int i; ! 9064: zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt); ! 9065: for(i=0; i<pTab->nCol; i++){ ! 9066: zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", "); ! 9067: } ! 9068: zWrite = idxAppendText(&rc, zWrite, ")"); ! 9069: break; ! 9070: } ! 9071: case SQLITE_UPDATE: { ! 9072: int i; ! 9073: zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt); ! 9074: for(i=0; i<pTab->nCol; i++){ ! 9075: zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", ! 9076: pTab->aCol[i].zName ! 9077: ); ! 9078: } ! 9079: break; ! 9080: } ! 9081: default: { ! 9082: assert( pWrite->eOp==SQLITE_DELETE ); ! 9083: if( rc==SQLITE_OK ){ ! 9084: zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt); ! 9085: if( zWrite==0 ) rc = SQLITE_NOMEM; ! 9086: } ! 9087: } ! 9088: } ! 9089: ! 9090: if( rc==SQLITE_OK ){ ! 9091: sqlite3_stmt *pX = 0; ! 9092: rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0); ! 9093: idxFinalize(&rc, pX); ! 9094: if( rc!=SQLITE_OK ){ ! 9095: idxDatabaseError(p->dbv, pzErr); ! 9096: } ! 9097: } ! 9098: sqlite3_free(zWrite); ! 9099: ! 9100: if( rc==SQLITE_OK ){ ! 9101: rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr); ! 9102: } ! 9103: ! 9104: return rc; ! 9105: } ! 9106: ! 9107: static int idxProcessTriggers(sqlite3expert *p, char **pzErr){ ! 9108: int rc = SQLITE_OK; ! 9109: IdxWrite *pEnd = 0; ! 9110: IdxWrite *pFirst = p->pWrite; ! 9111: ! 9112: while( rc==SQLITE_OK && pFirst!=pEnd ){ ! 9113: IdxWrite *pIter; ! 9114: for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){ ! 9115: rc = idxProcessOneTrigger(p, pIter, pzErr); ! 9116: } ! 9117: pEnd = pFirst; ! 9118: pFirst = p->pWrite; ! 9119: } ! 9120: ! 9121: return rc; ! 9122: } ! 9123: ! 9124: ! 9125: static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){ ! 9126: int rc = idxRegisterVtab(p); ! 9127: sqlite3_stmt *pSchema = 0; ! 9128: ! 9129: /* For each table in the main db schema: ! 9130: ** ! 9131: ** 1) Add an entry to the p->pTable list, and ! 9132: ** 2) Create the equivalent virtual table in dbv. ! 9133: */ ! 9134: rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg, ! 9135: "SELECT type, name, sql, 1 FROM sqlite_schema " ! 9136: "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' " ! 9137: " UNION ALL " ! 9138: "SELECT type, name, sql, 2 FROM sqlite_schema " ! 9139: "WHERE type = 'trigger'" ! 9140: " AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') " ! 9141: "ORDER BY 4, 1" ! 9142: ); ! 9143: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){ ! 9144: const char *zType = (const char*)sqlite3_column_text(pSchema, 0); ! 9145: const char *zName = (const char*)sqlite3_column_text(pSchema, 1); ! 9146: const char *zSql = (const char*)sqlite3_column_text(pSchema, 2); ! 9147: ! 9148: if( zType[0]=='v' || zType[1]=='r' ){ ! 9149: rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); ! 9150: }else{ ! 9151: IdxTable *pTab; ! 9152: rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg); ! 9153: if( rc==SQLITE_OK ){ ! 9154: int i; ! 9155: char *zInner = 0; ! 9156: char *zOuter = 0; ! 9157: pTab->pNext = p->pTable; ! 9158: p->pTable = pTab; ! 9159: ! 9160: /* The statement the vtab will pass to sqlite3_declare_vtab() */ ! 9161: zInner = idxAppendText(&rc, 0, "CREATE TABLE x("); ! 9162: for(i=0; i<pTab->nCol; i++){ ! 9163: zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", ! 9164: (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl ! 9165: ); ! 9166: } ! 9167: zInner = idxAppendText(&rc, zInner, ")"); ! 9168: ! 9169: /* The CVT statement to create the vtab */ ! 9170: zOuter = idxAppendText(&rc, 0, ! 9171: "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner ! 9172: ); ! 9173: if( rc==SQLITE_OK ){ ! 9174: rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg); ! 9175: } ! 9176: sqlite3_free(zInner); ! 9177: sqlite3_free(zOuter); ! 9178: } ! 9179: } ! 9180: } ! 9181: idxFinalize(&rc, pSchema); ! 9182: return rc; ! 9183: } ! 9184: ! 9185: struct IdxSampleCtx { ! 9186: int iTarget; ! 9187: double target; /* Target nRet/nRow value */ ! 9188: double nRow; /* Number of rows seen */ ! 9189: double nRet; /* Number of rows returned */ ! 9190: }; ! 9191: ! 9192: static void idxSampleFunc( ! 9193: sqlite3_context *pCtx, ! 9194: int argc, ! 9195: sqlite3_value **argv ! 9196: ){ ! 9197: struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx); ! 9198: int bRet; ! 9199: ! 9200: (void)argv; ! 9201: assert( argc==0 ); ! 9202: if( p->nRow==0.0 ){ ! 9203: bRet = 1; ! 9204: }else{ ! 9205: bRet = (p->nRet / p->nRow) <= p->target; ! 9206: if( bRet==0 ){ ! 9207: unsigned short rnd; ! 9208: sqlite3_randomness(2, (void*)&rnd); ! 9209: bRet = ((int)rnd % 100) <= p->iTarget; ! 9210: } ! 9211: } ! 9212: ! 9213: sqlite3_result_int(pCtx, bRet); ! 9214: p->nRow += 1.0; ! 9215: p->nRet += (double)bRet; ! 9216: } ! 9217: ! 9218: struct IdxRemCtx { ! 9219: int nSlot; ! 9220: struct IdxRemSlot { ! 9221: int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ ! 9222: i64 iVal; /* SQLITE_INTEGER value */ ! 9223: double rVal; /* SQLITE_FLOAT value */ ! 9224: int nByte; /* Bytes of space allocated at z */ ! 9225: int n; /* Size of buffer z */ ! 9226: char *z; /* SQLITE_TEXT/BLOB value */ ! 9227: } aSlot[1]; ! 9228: }; ! 9229: ! 9230: /* ! 9231: ** Implementation of scalar function rem(). ! 9232: */ ! 9233: static void idxRemFunc( ! 9234: sqlite3_context *pCtx, ! 9235: int argc, ! 9236: sqlite3_value **argv ! 9237: ){ ! 9238: struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx); ! 9239: struct IdxRemSlot *pSlot; ! 9240: int iSlot; ! 9241: assert( argc==2 ); ! 9242: ! 9243: iSlot = sqlite3_value_int(argv[0]); ! 9244: assert( iSlot<=p->nSlot ); ! 9245: pSlot = &p->aSlot[iSlot]; ! 9246: ! 9247: switch( pSlot->eType ){ ! 9248: case SQLITE_NULL: ! 9249: /* no-op */ ! 9250: break; ! 9251: ! 9252: case SQLITE_INTEGER: ! 9253: sqlite3_result_int64(pCtx, pSlot->iVal); ! 9254: break; ! 9255: ! 9256: case SQLITE_FLOAT: ! 9257: sqlite3_result_double(pCtx, pSlot->rVal); ! 9258: break; ! 9259: ! 9260: case SQLITE_BLOB: ! 9261: sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); ! 9262: break; ! 9263: ! 9264: case SQLITE_TEXT: ! 9265: sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); ! 9266: break; ! 9267: } ! 9268: ! 9269: pSlot->eType = sqlite3_value_type(argv[1]); ! 9270: switch( pSlot->eType ){ ! 9271: case SQLITE_NULL: ! 9272: /* no-op */ ! 9273: break; ! 9274: ! 9275: case SQLITE_INTEGER: ! 9276: pSlot->iVal = sqlite3_value_int64(argv[1]); ! 9277: break; ! 9278: ! 9279: case SQLITE_FLOAT: ! 9280: pSlot->rVal = sqlite3_value_double(argv[1]); ! 9281: break; ! 9282: ! 9283: case SQLITE_BLOB: ! 9284: case SQLITE_TEXT: { ! 9285: int nByte = sqlite3_value_bytes(argv[1]); ! 9286: if( nByte>pSlot->nByte ){ ! 9287: char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); ! 9288: if( zNew==0 ){ ! 9289: sqlite3_result_error_nomem(pCtx); ! 9290: return; ! 9291: } ! 9292: pSlot->nByte = nByte*2; ! 9293: pSlot->z = zNew; ! 9294: } ! 9295: pSlot->n = nByte; ! 9296: if( pSlot->eType==SQLITE_BLOB ){ ! 9297: memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte); ! 9298: }else{ ! 9299: memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte); ! 9300: } ! 9301: break; ! 9302: } ! 9303: } ! 9304: } ! 9305: ! 9306: static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){ ! 9307: int rc = SQLITE_OK; ! 9308: const char *zMax = ! 9309: "SELECT max(i.seqno) FROM " ! 9310: " sqlite_schema AS s, " ! 9311: " pragma_index_list(s.name) AS l, " ! 9312: " pragma_index_info(l.name) AS i " ! 9313: "WHERE s.type = 'table'"; ! 9314: sqlite3_stmt *pMax = 0; ! 9315: ! 9316: *pnMax = 0; ! 9317: rc = idxPrepareStmt(db, &pMax, pzErr, zMax); ! 9318: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ ! 9319: *pnMax = sqlite3_column_int(pMax, 0) + 1; ! 9320: } ! 9321: idxFinalize(&rc, pMax); ! 9322: ! 9323: return rc; ! 9324: } ! 9325: ! 9326: static int idxPopulateOneStat1( ! 9327: sqlite3expert *p, ! 9328: sqlite3_stmt *pIndexXInfo, ! 9329: sqlite3_stmt *pWriteStat, ! 9330: const char *zTab, ! 9331: const char *zIdx, ! 9332: char **pzErr ! 9333: ){ ! 9334: char *zCols = 0; ! 9335: char *zOrder = 0; ! 9336: char *zQuery = 0; ! 9337: int nCol = 0; ! 9338: int i; ! 9339: sqlite3_stmt *pQuery = 0; ! 9340: int *aStat = 0; ! 9341: int rc = SQLITE_OK; ! 9342: ! 9343: assert( p->iSample>0 ); ! 9344: ! 9345: /* Formulate the query text */ ! 9346: sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC); ! 9347: while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){ ! 9348: const char *zComma = zCols==0 ? "" : ", "; ! 9349: const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); ! 9350: const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); ! 9351: zCols = idxAppendText(&rc, zCols, ! 9352: "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl ! 9353: ); ! 9354: zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); ! 9355: } ! 9356: sqlite3_reset(pIndexXInfo); ! 9357: if( rc==SQLITE_OK ){ ! 9358: if( p->iSample==100 ){ ! 9359: zQuery = sqlite3_mprintf( ! 9360: "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder ! 9361: ); ! 9362: }else{ ! 9363: zQuery = sqlite3_mprintf( ! 9364: "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder ! 9365: ); ! 9366: } ! 9367: } ! 9368: sqlite3_free(zCols); ! 9369: sqlite3_free(zOrder); ! 9370: ! 9371: /* Formulate the query text */ ! 9372: if( rc==SQLITE_OK ){ ! 9373: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); ! 9374: rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); ! 9375: } ! 9376: sqlite3_free(zQuery); ! 9377: ! 9378: if( rc==SQLITE_OK ){ ! 9379: aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); ! 9380: } ! 9381: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ ! 9382: IdxHashEntry *pEntry; ! 9383: char *zStat = 0; ! 9384: for(i=0; i<=nCol; i++) aStat[i] = 1; ! 9385: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ ! 9386: aStat[0]++; ! 9387: for(i=0; i<nCol; i++){ ! 9388: if( sqlite3_column_int(pQuery, i)==0 ) break; ! 9389: } ! 9390: for(/*no-op*/; i<nCol; i++){ ! 9391: aStat[i+1]++; ! 9392: } ! 9393: } ! 9394: ! 9395: if( rc==SQLITE_OK ){ ! 9396: int s0 = aStat[0]; ! 9397: zStat = sqlite3_mprintf("%d", s0); ! 9398: if( zStat==0 ) rc = SQLITE_NOMEM; ! 9399: for(i=1; rc==SQLITE_OK && i<=nCol; i++){ ! 9400: zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]); ! 9401: } ! 9402: } ! 9403: ! 9404: if( rc==SQLITE_OK ){ ! 9405: sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); ! 9406: sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC); ! 9407: sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC); ! 9408: sqlite3_step(pWriteStat); ! 9409: rc = sqlite3_reset(pWriteStat); ! 9410: } ! 9411: ! 9412: pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx)); ! 9413: if( pEntry ){ ! 9414: assert( pEntry->zVal2==0 ); ! 9415: pEntry->zVal2 = zStat; ! 9416: }else{ ! 9417: sqlite3_free(zStat); ! 9418: } ! 9419: } ! 9420: sqlite3_free(aStat); ! 9421: idxFinalize(&rc, pQuery); ! 9422: ! 9423: return rc; ! 9424: } ! 9425: ! 9426: static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){ ! 9427: int rc; ! 9428: char *zSql; ! 9429: ! 9430: rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); ! 9431: if( rc!=SQLITE_OK ) return rc; ! 9432: ! 9433: zSql = sqlite3_mprintf( ! 9434: "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab ! 9435: ); ! 9436: if( zSql==0 ) return SQLITE_NOMEM; ! 9437: rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0); ! 9438: sqlite3_free(zSql); ! 9439: ! 9440: return rc; ! 9441: } ! 9442: ! 9443: /* ! 9444: ** This function is called as part of sqlite3_expert_analyze(). Candidate ! 9445: ** indexes have already been created in database sqlite3expert.dbm, this ! 9446: ** function populates sqlite_stat1 table in the same database. ! 9447: ** ! 9448: ** The stat1 data is generated by querying the ! 9449: */ ! 9450: static int idxPopulateStat1(sqlite3expert *p, char **pzErr){ ! 9451: int rc = SQLITE_OK; ! 9452: int nMax =0; ! 9453: struct IdxRemCtx *pCtx = 0; ! 9454: struct IdxSampleCtx samplectx; ! 9455: int i; ! 9456: i64 iPrev = -100000; ! 9457: sqlite3_stmt *pAllIndex = 0; ! 9458: sqlite3_stmt *pIndexXInfo = 0; ! 9459: sqlite3_stmt *pWrite = 0; ! 9460: ! 9461: const char *zAllIndex = ! 9462: "SELECT s.rowid, s.name, l.name FROM " ! 9463: " sqlite_schema AS s, " ! 9464: " pragma_index_list(s.name) AS l " ! 9465: "WHERE s.type = 'table'"; ! 9466: const char *zIndexXInfo = ! 9467: "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key"; ! 9468: const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)"; ! 9469: ! 9470: /* If iSample==0, no sqlite_stat1 data is required. */ ! 9471: if( p->iSample==0 ) return SQLITE_OK; ! 9472: ! 9473: rc = idxLargestIndex(p->dbm, &nMax, pzErr); ! 9474: if( nMax<=0 || rc!=SQLITE_OK ) return rc; ! 9475: ! 9476: rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); ! 9477: ! 9478: if( rc==SQLITE_OK ){ ! 9479: int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); ! 9480: pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); ! 9481: } ! 9482: ! 9483: if( rc==SQLITE_OK ){ ! 9484: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); ! 9485: rc = sqlite3_create_function( ! 9486: dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0 ! 9487: ); ! 9488: } ! 9489: if( rc==SQLITE_OK ){ ! 9490: rc = sqlite3_create_function( ! 9491: p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 ! 9492: ); ! 9493: } ! 9494: ! 9495: if( rc==SQLITE_OK ){ ! 9496: pCtx->nSlot = nMax+1; ! 9497: rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); ! 9498: } ! 9499: if( rc==SQLITE_OK ){ ! 9500: rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); ! 9501: } ! 9502: if( rc==SQLITE_OK ){ ! 9503: rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite); ! 9504: } ! 9505: ! 9506: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){ ! 9507: i64 iRowid = sqlite3_column_int64(pAllIndex, 0); ! 9508: const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1); ! 9509: const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2); ! 9510: if( p->iSample<100 && iPrev!=iRowid ){ ! 9511: samplectx.target = (double)p->iSample / 100.0; ! 9512: samplectx.iTarget = p->iSample; ! 9513: samplectx.nRow = 0.0; ! 9514: samplectx.nRet = 0.0; ! 9515: rc = idxBuildSampleTable(p, zTab); ! 9516: if( rc!=SQLITE_OK ) break; ! 9517: } ! 9518: rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr); ! 9519: iPrev = iRowid; ! 9520: } ! 9521: if( rc==SQLITE_OK && p->iSample<100 ){ ! 9522: rc = sqlite3_exec(p->dbv, ! 9523: "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0 ! 9524: ); ! 9525: } ! 9526: ! 9527: idxFinalize(&rc, pAllIndex); ! 9528: idxFinalize(&rc, pIndexXInfo); ! 9529: idxFinalize(&rc, pWrite); ! 9530: ! 9531: for(i=0; i<pCtx->nSlot; i++){ ! 9532: sqlite3_free(pCtx->aSlot[i].z); ! 9533: } ! 9534: sqlite3_free(pCtx); ! 9535: ! 9536: if( rc==SQLITE_OK ){ ! 9537: rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0); ! 9538: } ! 9539: ! 9540: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); ! 9541: return rc; ! 9542: } ! 9543: ! 9544: /* ! 9545: ** Allocate a new sqlite3expert object. ! 9546: */ ! 9547: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){ ! 9548: int rc = SQLITE_OK; ! 9549: sqlite3expert *pNew; ! 9550: ! 9551: pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert)); ! 9552: ! 9553: /* Open two in-memory databases to work with. The "vtab database" (dbv) ! 9554: ** will contain a virtual table corresponding to each real table in ! 9555: ** the user database schema, and a copy of each view. It is used to ! 9556: ** collect information regarding the WHERE, ORDER BY and other clauses ! 9557: ** of the user's query. ! 9558: */ ! 9559: if( rc==SQLITE_OK ){ ! 9560: pNew->db = db; ! 9561: pNew->iSample = 100; ! 9562: rc = sqlite3_open(":memory:", &pNew->dbv); ! 9563: } ! 9564: if( rc==SQLITE_OK ){ ! 9565: rc = sqlite3_open(":memory:", &pNew->dbm); ! 9566: if( rc==SQLITE_OK ){ ! 9567: sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0); ! 9568: } ! 9569: } ! 9570: ! 9571: ! 9572: /* Copy the entire schema of database [db] into [dbm]. */ ! 9573: if( rc==SQLITE_OK ){ ! 9574: sqlite3_stmt *pSql; ! 9575: rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, ! 9576: "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" ! 9577: " AND sql NOT LIKE 'CREATE VIRTUAL %%'" ! 9578: ); ! 9579: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ! 9580: const char *zSql = (const char*)sqlite3_column_text(pSql, 0); ! 9581: rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); ! 9582: } ! 9583: idxFinalize(&rc, pSql); ! 9584: } ! 9585: ! 9586: /* Create the vtab schema */ ! 9587: if( rc==SQLITE_OK ){ ! 9588: rc = idxCreateVtabSchema(pNew, pzErrmsg); ! 9589: } ! 9590: ! 9591: /* Register the auth callback with dbv */ ! 9592: if( rc==SQLITE_OK ){ ! 9593: sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew); ! 9594: } ! 9595: ! 9596: /* If an error has occurred, free the new object and reutrn NULL. Otherwise, ! 9597: ** return the new sqlite3expert handle. */ ! 9598: if( rc!=SQLITE_OK ){ ! 9599: sqlite3_expert_destroy(pNew); ! 9600: pNew = 0; ! 9601: } ! 9602: return pNew; ! 9603: } ! 9604: ! 9605: /* ! 9606: ** Configure an sqlite3expert object. ! 9607: */ ! 9608: int sqlite3_expert_config(sqlite3expert *p, int op, ...){ ! 9609: int rc = SQLITE_OK; ! 9610: va_list ap; ! 9611: va_start(ap, op); ! 9612: switch( op ){ ! 9613: case EXPERT_CONFIG_SAMPLE: { ! 9614: int iVal = va_arg(ap, int); ! 9615: if( iVal<0 ) iVal = 0; ! 9616: if( iVal>100 ) iVal = 100; ! 9617: p->iSample = iVal; ! 9618: break; ! 9619: } ! 9620: default: ! 9621: rc = SQLITE_NOTFOUND; ! 9622: break; ! 9623: } ! 9624: ! 9625: va_end(ap); ! 9626: return rc; ! 9627: } ! 9628: ! 9629: /* ! 9630: ** Add an SQL statement to the analysis. ! 9631: */ ! 9632: int sqlite3_expert_sql( ! 9633: sqlite3expert *p, /* From sqlite3_expert_new() */ ! 9634: const char *zSql, /* SQL statement to add */ ! 9635: char **pzErr /* OUT: Error message (if any) */ ! 9636: ){ ! 9637: IdxScan *pScanOrig = p->pScan; ! 9638: IdxStatement *pStmtOrig = p->pStatement; ! 9639: int rc = SQLITE_OK; ! 9640: const char *zStmt = zSql; ! 9641: ! 9642: if( p->bRun ) return SQLITE_MISUSE; ! 9643: ! 9644: while( rc==SQLITE_OK && zStmt && zStmt[0] ){ ! 9645: sqlite3_stmt *pStmt = 0; ! 9646: rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); ! 9647: if( rc==SQLITE_OK ){ ! 9648: if( pStmt ){ ! 9649: IdxStatement *pNew; ! 9650: const char *z = sqlite3_sql(pStmt); ! 9651: int n = STRLEN(z); ! 9652: pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); ! 9653: if( rc==SQLITE_OK ){ ! 9654: pNew->zSql = (char*)&pNew[1]; ! 9655: memcpy(pNew->zSql, z, n+1); ! 9656: pNew->pNext = p->pStatement; ! 9657: if( p->pStatement ) pNew->iId = p->pStatement->iId+1; ! 9658: p->pStatement = pNew; ! 9659: } ! 9660: sqlite3_finalize(pStmt); ! 9661: } ! 9662: }else{ ! 9663: idxDatabaseError(p->dbv, pzErr); ! 9664: } ! 9665: } ! 9666: ! 9667: if( rc!=SQLITE_OK ){ ! 9668: idxScanFree(p->pScan, pScanOrig); ! 9669: idxStatementFree(p->pStatement, pStmtOrig); ! 9670: p->pScan = pScanOrig; ! 9671: p->pStatement = pStmtOrig; ! 9672: } ! 9673: ! 9674: return rc; ! 9675: } ! 9676: ! 9677: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){ ! 9678: int rc; ! 9679: IdxHashEntry *pEntry; ! 9680: ! 9681: /* Do trigger processing to collect any extra IdxScan structures */ ! 9682: rc = idxProcessTriggers(p, pzErr); ! 9683: ! 9684: /* Create candidate indexes within the in-memory database file */ ! 9685: if( rc==SQLITE_OK ){ ! 9686: rc = idxCreateCandidates(p); ! 9687: } ! 9688: ! 9689: /* Generate the stat1 data */ ! 9690: if( rc==SQLITE_OK ){ ! 9691: rc = idxPopulateStat1(p, pzErr); ! 9692: } ! 9693: ! 9694: /* Formulate the EXPERT_REPORT_CANDIDATES text */ ! 9695: for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ ! 9696: p->zCandidates = idxAppendText(&rc, p->zCandidates, ! 9697: "%s;%s%s\n", pEntry->zVal, ! 9698: pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2 ! 9699: ); ! 9700: } ! 9701: ! 9702: /* Figure out which of the candidate indexes are preferred by the query ! 9703: ** planner and report the results to the user. */ ! 9704: if( rc==SQLITE_OK ){ ! 9705: rc = idxFindIndexes(p, pzErr); ! 9706: } ! 9707: ! 9708: if( rc==SQLITE_OK ){ ! 9709: p->bRun = 1; ! 9710: } ! 9711: return rc; ! 9712: } ! 9713: ! 9714: /* ! 9715: ** Return the total number of statements that have been added to this ! 9716: ** sqlite3expert using sqlite3_expert_sql(). ! 9717: */ ! 9718: int sqlite3_expert_count(sqlite3expert *p){ ! 9719: int nRet = 0; ! 9720: if( p->pStatement ) nRet = p->pStatement->iId+1; ! 9721: return nRet; ! 9722: } ! 9723: ! 9724: /* ! 9725: ** Return a component of the report. ! 9726: */ ! 9727: const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){ ! 9728: const char *zRet = 0; ! 9729: IdxStatement *pStmt; ! 9730: ! 9731: if( p->bRun==0 ) return 0; ! 9732: for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext); ! 9733: switch( eReport ){ ! 9734: case EXPERT_REPORT_SQL: ! 9735: if( pStmt ) zRet = pStmt->zSql; ! 9736: break; ! 9737: case EXPERT_REPORT_INDEXES: ! 9738: if( pStmt ) zRet = pStmt->zIdx; ! 9739: break; ! 9740: case EXPERT_REPORT_PLAN: ! 9741: if( pStmt ) zRet = pStmt->zEQP; ! 9742: break; ! 9743: case EXPERT_REPORT_CANDIDATES: ! 9744: zRet = p->zCandidates; ! 9745: break; ! 9746: } ! 9747: return zRet; ! 9748: } ! 9749: ! 9750: /* ! 9751: ** Free an sqlite3expert object. ! 9752: */ ! 9753: void sqlite3_expert_destroy(sqlite3expert *p){ ! 9754: if( p ){ ! 9755: sqlite3_close(p->dbm); ! 9756: sqlite3_close(p->dbv); ! 9757: idxScanFree(p->pScan, 0); ! 9758: idxStatementFree(p->pStatement, 0); ! 9759: idxTableFree(p->pTable); ! 9760: idxWriteFree(p->pWrite); ! 9761: idxHashClear(&p->hIdx); ! 9762: sqlite3_free(p->zCandidates); ! 9763: sqlite3_free(p); ! 9764: } ! 9765: } ! 9766: ! 9767: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ ! 9768: ! 9769: /************************* End ../ext/expert/sqlite3expert.c ********************/ ! 9770: ! 9771: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ! 9772: /************************* Begin ../ext/misc/dbdata.c ******************/ ! 9773: /* ! 9774: ** 2019-04-17 ! 9775: ** ! 9776: ** The author disclaims copyright to this source code. In place of ! 9777: ** a legal notice, here is a blessing: ! 9778: ** ! 9779: ** May you do good and not evil. ! 9780: ** May you find forgiveness for yourself and forgive others. ! 9781: ** May you share freely, never taking more than you give. ! 9782: ** ! 9783: ****************************************************************************** ! 9784: ** ! 9785: ** This file contains an implementation of two eponymous virtual tables, ! 9786: ** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the ! 9787: ** "sqlite_dbpage" eponymous virtual table be available. ! 9788: ** ! 9789: ** SQLITE_DBDATA: ! 9790: ** sqlite_dbdata is used to extract data directly from a database b-tree ! 9791: ** page and its associated overflow pages, bypassing the b-tree layer. ! 9792: ** The table schema is equivalent to: ! 9793: ** ! 9794: ** CREATE TABLE sqlite_dbdata( ! 9795: ** pgno INTEGER, ! 9796: ** cell INTEGER, ! 9797: ** field INTEGER, ! 9798: ** value ANY, ! 9799: ** schema TEXT HIDDEN ! 9800: ** ); ! 9801: ** ! 9802: ** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE ! 9803: ** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND ! 9804: ** "schema". ! 9805: ** ! 9806: ** Each page of the database is inspected. If it cannot be interpreted as ! 9807: ** a b-tree page, or if it is a b-tree page containing 0 entries, the ! 9808: ** sqlite_dbdata table contains no rows for that page. Otherwise, the ! 9809: ** table contains one row for each field in the record associated with ! 9810: ** each cell on the page. For intkey b-trees, the key value is stored in ! 9811: ** field -1. ! 9812: ** ! 9813: ** For example, for the database: ! 9814: ** ! 9815: ** CREATE TABLE t1(a, b); -- root page is page 2 ! 9816: ** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five'); ! 9817: ** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten'); ! 9818: ** ! 9819: ** the sqlite_dbdata table contains, as well as from entries related to ! 9820: ** page 1, content equivalent to: ! 9821: ** ! 9822: ** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES ! 9823: ** (2, 0, -1, 5 ), ! 9824: ** (2, 0, 0, 'v' ), ! 9825: ** (2, 0, 1, 'five'), ! 9826: ** (2, 1, -1, 10 ), ! 9827: ** (2, 1, 0, 'x' ), ! 9828: ** (2, 1, 1, 'ten' ); ! 9829: ** ! 9830: ** If database corruption is encountered, this module does not report an ! 9831: ** error. Instead, it attempts to extract as much data as possible and ! 9832: ** ignores the corruption. ! 9833: ** ! 9834: ** SQLITE_DBPTR: ! 9835: ** The sqlite_dbptr table has the following schema: ! 9836: ** ! 9837: ** CREATE TABLE sqlite_dbptr( ! 9838: ** pgno INTEGER, ! 9839: ** child INTEGER, ! 9840: ** schema TEXT HIDDEN ! 9841: ** ); ! 9842: ** ! 9843: ** It contains one entry for each b-tree pointer between a parent and ! 9844: ** child page in the database. ! 9845: */ ! 9846: #if !defined(SQLITEINT_H) ! 9847: /* #include "sqlite3ext.h" */ ! 9848: ! 9849: /* typedef unsigned char u8; */ ! 9850: ! 9851: #endif ! 9852: SQLITE_EXTENSION_INIT1 ! 9853: #include <string.h> ! 9854: #include <assert.h> ! 9855: ! 9856: #define DBDATA_PADDING_BYTES 100 ! 9857: ! 9858: typedef struct DbdataTable DbdataTable; ! 9859: typedef struct DbdataCursor DbdataCursor; ! 9860: ! 9861: /* Cursor object */ ! 9862: struct DbdataCursor { ! 9863: sqlite3_vtab_cursor base; /* Base class. Must be first */ ! 9864: sqlite3_stmt *pStmt; /* For fetching database pages */ ! 9865: ! 9866: int iPgno; /* Current page number */ ! 9867: u8 *aPage; /* Buffer containing page */ ! 9868: int nPage; /* Size of aPage[] in bytes */ ! 9869: int nCell; /* Number of cells on aPage[] */ ! 9870: int iCell; /* Current cell number */ ! 9871: int bOnePage; /* True to stop after one page */ ! 9872: int szDb; ! 9873: sqlite3_int64 iRowid; ! 9874: ! 9875: /* Only for the sqlite_dbdata table */ ! 9876: u8 *pRec; /* Buffer containing current record */ ! 9877: int nRec; /* Size of pRec[] in bytes */ ! 9878: int nHdr; /* Size of header in bytes */ ! 9879: int iField; /* Current field number */ ! 9880: u8 *pHdrPtr; ! 9881: u8 *pPtr; ! 9882: ! 9883: sqlite3_int64 iIntkey; /* Integer key value */ ! 9884: }; ! 9885: ! 9886: /* Table object */ ! 9887: struct DbdataTable { ! 9888: sqlite3_vtab base; /* Base class. Must be first */ ! 9889: sqlite3 *db; /* The database connection */ ! 9890: sqlite3_stmt *pStmt; /* For fetching database pages */ ! 9891: int bPtr; /* True for sqlite3_dbptr table */ ! 9892: }; ! 9893: ! 9894: /* Column and schema definitions for sqlite_dbdata */ ! 9895: #define DBDATA_COLUMN_PGNO 0 ! 9896: #define DBDATA_COLUMN_CELL 1 ! 9897: #define DBDATA_COLUMN_FIELD 2 ! 9898: #define DBDATA_COLUMN_VALUE 3 ! 9899: #define DBDATA_COLUMN_SCHEMA 4 ! 9900: #define DBDATA_SCHEMA \ ! 9901: "CREATE TABLE x(" \ ! 9902: " pgno INTEGER," \ ! 9903: " cell INTEGER," \ ! 9904: " field INTEGER," \ ! 9905: " value ANY," \ ! 9906: " schema TEXT HIDDEN" \ ! 9907: ")" ! 9908: ! 9909: /* Column and schema definitions for sqlite_dbptr */ ! 9910: #define DBPTR_COLUMN_PGNO 0 ! 9911: #define DBPTR_COLUMN_CHILD 1 ! 9912: #define DBPTR_COLUMN_SCHEMA 2 ! 9913: #define DBPTR_SCHEMA \ ! 9914: "CREATE TABLE x(" \ ! 9915: " pgno INTEGER," \ ! 9916: " child INTEGER," \ ! 9917: " schema TEXT HIDDEN" \ ! 9918: ")" ! 9919: ! 9920: /* ! 9921: ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual ! 9922: ** table. ! 9923: */ ! 9924: static int dbdataConnect( ! 9925: sqlite3 *db, ! 9926: void *pAux, ! 9927: int argc, const char *const*argv, ! 9928: sqlite3_vtab **ppVtab, ! 9929: char **pzErr ! 9930: ){ ! 9931: DbdataTable *pTab = 0; ! 9932: int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); ! 9933: ! 9934: if( rc==SQLITE_OK ){ ! 9935: pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable)); ! 9936: if( pTab==0 ){ ! 9937: rc = SQLITE_NOMEM; ! 9938: }else{ ! 9939: memset(pTab, 0, sizeof(DbdataTable)); ! 9940: pTab->db = db; ! 9941: pTab->bPtr = (pAux!=0); ! 9942: } ! 9943: } ! 9944: ! 9945: *ppVtab = (sqlite3_vtab*)pTab; ! 9946: return rc; ! 9947: } ! 9948: ! 9949: /* ! 9950: ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table. ! 9951: */ ! 9952: static int dbdataDisconnect(sqlite3_vtab *pVtab){ ! 9953: DbdataTable *pTab = (DbdataTable*)pVtab; ! 9954: if( pTab ){ ! 9955: sqlite3_finalize(pTab->pStmt); ! 9956: sqlite3_free(pVtab); ! 9957: } ! 9958: return SQLITE_OK; ! 9959: } ! 9960: ! 9961: /* ! 9962: ** This function interprets two types of constraints: ! 9963: ** ! 9964: ** schema=? ! 9965: ** pgno=? ! 9966: ** ! 9967: ** If neither are present, idxNum is set to 0. If schema=? is present, ! 9968: ** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit ! 9969: ** in idxNum is set. ! 9970: ** ! 9971: ** If both parameters are present, schema is in position 0 and pgno in ! 9972: ** position 1. ! 9973: */ ! 9974: static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){ ! 9975: DbdataTable *pTab = (DbdataTable*)tab; ! 9976: int i; ! 9977: int iSchema = -1; ! 9978: int iPgno = -1; ! 9979: int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA); ! 9980: ! 9981: for(i=0; i<pIdx->nConstraint; i++){ ! 9982: struct sqlite3_index_constraint *p = &pIdx->aConstraint[i]; ! 9983: if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ! 9984: if( p->iColumn==colSchema ){ ! 9985: if( p->usable==0 ) return SQLITE_CONSTRAINT; ! 9986: iSchema = i; ! 9987: } ! 9988: if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){ ! 9989: iPgno = i; ! 9990: } ! 9991: } ! 9992: } ! 9993: ! 9994: if( iSchema>=0 ){ ! 9995: pIdx->aConstraintUsage[iSchema].argvIndex = 1; ! 9996: pIdx->aConstraintUsage[iSchema].omit = 1; ! 9997: } ! 9998: if( iPgno>=0 ){ ! 9999: pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0); ! 10000: pIdx->aConstraintUsage[iPgno].omit = 1; ! 10001: pIdx->estimatedCost = 100; ! 10002: pIdx->estimatedRows = 50; ! 10003: ! 10004: if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){ ! 10005: int iCol = pIdx->aOrderBy[0].iColumn; ! 10006: if( pIdx->nOrderBy==1 ){ ! 10007: pIdx->orderByConsumed = (iCol==0 || iCol==1); ! 10008: }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){ ! 10009: pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1); ! 10010: } ! 10011: } ! 10012: ! 10013: }else{ ! 10014: pIdx->estimatedCost = 100000000; ! 10015: pIdx->estimatedRows = 1000000000; ! 10016: } ! 10017: pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00); ! 10018: return SQLITE_OK; ! 10019: } ! 10020: ! 10021: /* ! 10022: ** Open a new sqlite_dbdata or sqlite_dbptr cursor. ! 10023: */ ! 10024: static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ ! 10025: DbdataCursor *pCsr; ! 10026: ! 10027: pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor)); ! 10028: if( pCsr==0 ){ ! 10029: return SQLITE_NOMEM; ! 10030: }else{ ! 10031: memset(pCsr, 0, sizeof(DbdataCursor)); ! 10032: pCsr->base.pVtab = pVTab; ! 10033: } ! 10034: ! 10035: *ppCursor = (sqlite3_vtab_cursor *)pCsr; ! 10036: return SQLITE_OK; ! 10037: } ! 10038: ! 10039: /* ! 10040: ** Restore a cursor object to the state it was in when first allocated ! 10041: ** by dbdataOpen(). ! 10042: */ ! 10043: static void dbdataResetCursor(DbdataCursor *pCsr){ ! 10044: DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab); ! 10045: if( pTab->pStmt==0 ){ ! 10046: pTab->pStmt = pCsr->pStmt; ! 10047: }else{ ! 10048: sqlite3_finalize(pCsr->pStmt); ! 10049: } ! 10050: pCsr->pStmt = 0; ! 10051: pCsr->iPgno = 1; ! 10052: pCsr->iCell = 0; ! 10053: pCsr->iField = 0; ! 10054: pCsr->bOnePage = 0; ! 10055: sqlite3_free(pCsr->aPage); ! 10056: sqlite3_free(pCsr->pRec); ! 10057: pCsr->pRec = 0; ! 10058: pCsr->aPage = 0; ! 10059: } ! 10060: ! 10061: /* ! 10062: ** Close an sqlite_dbdata or sqlite_dbptr cursor. ! 10063: */ ! 10064: static int dbdataClose(sqlite3_vtab_cursor *pCursor){ ! 10065: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10066: dbdataResetCursor(pCsr); ! 10067: sqlite3_free(pCsr); ! 10068: return SQLITE_OK; ! 10069: } ! 10070: ! 10071: /* ! 10072: ** Utility methods to decode 16 and 32-bit big-endian unsigned integers. ! 10073: */ ! 10074: static unsigned int get_uint16(unsigned char *a){ ! 10075: return (a[0]<<8)|a[1]; ! 10076: } ! 10077: static unsigned int get_uint32(unsigned char *a){ ! 10078: return ((unsigned int)a[0]<<24) ! 10079: | ((unsigned int)a[1]<<16) ! 10080: | ((unsigned int)a[2]<<8) ! 10081: | ((unsigned int)a[3]); ! 10082: } ! 10083: ! 10084: /* ! 10085: ** Load page pgno from the database via the sqlite_dbpage virtual table. ! 10086: ** If successful, set (*ppPage) to point to a buffer containing the page ! 10087: ** data, (*pnPage) to the size of that buffer in bytes and return ! 10088: ** SQLITE_OK. In this case it is the responsibility of the caller to ! 10089: ** eventually free the buffer using sqlite3_free(). ! 10090: ** ! 10091: ** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and ! 10092: ** return an SQLite error code. ! 10093: */ ! 10094: static int dbdataLoadPage( ! 10095: DbdataCursor *pCsr, /* Cursor object */ ! 10096: unsigned int pgno, /* Page number of page to load */ ! 10097: u8 **ppPage, /* OUT: pointer to page buffer */ ! 10098: int *pnPage /* OUT: Size of (*ppPage) in bytes */ ! 10099: ){ ! 10100: int rc2; ! 10101: int rc = SQLITE_OK; ! 10102: sqlite3_stmt *pStmt = pCsr->pStmt; ! 10103: ! 10104: *ppPage = 0; ! 10105: *pnPage = 0; ! 10106: sqlite3_bind_int64(pStmt, 2, pgno); ! 10107: if( SQLITE_ROW==sqlite3_step(pStmt) ){ ! 10108: int nCopy = sqlite3_column_bytes(pStmt, 0); ! 10109: if( nCopy>0 ){ ! 10110: u8 *pPage; ! 10111: pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES); ! 10112: if( pPage==0 ){ ! 10113: rc = SQLITE_NOMEM; ! 10114: }else{ ! 10115: const u8 *pCopy = sqlite3_column_blob(pStmt, 0); ! 10116: memcpy(pPage, pCopy, nCopy); ! 10117: memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES); ! 10118: } ! 10119: *ppPage = pPage; ! 10120: *pnPage = nCopy; ! 10121: } ! 10122: } ! 10123: rc2 = sqlite3_reset(pStmt); ! 10124: if( rc==SQLITE_OK ) rc = rc2; ! 10125: ! 10126: return rc; ! 10127: } ! 10128: ! 10129: /* ! 10130: ** Read a varint. Put the value in *pVal and return the number of bytes. ! 10131: */ ! 10132: static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){ ! 10133: sqlite3_int64 v = 0; ! 10134: int i; ! 10135: for(i=0; i<8; i++){ ! 10136: v = (v<<7) + (z[i]&0x7f); ! 10137: if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } ! 10138: } ! 10139: v = (v<<8) + (z[i]&0xff); ! 10140: *pVal = v; ! 10141: return 9; ! 10142: } ! 10143: ! 10144: /* ! 10145: ** Return the number of bytes of space used by an SQLite value of type ! 10146: ** eType. ! 10147: */ ! 10148: static int dbdataValueBytes(int eType){ ! 10149: switch( eType ){ ! 10150: case 0: case 8: case 9: ! 10151: case 10: case 11: ! 10152: return 0; ! 10153: case 1: ! 10154: return 1; ! 10155: case 2: ! 10156: return 2; ! 10157: case 3: ! 10158: return 3; ! 10159: case 4: ! 10160: return 4; ! 10161: case 5: ! 10162: return 6; ! 10163: case 6: ! 10164: case 7: ! 10165: return 8; ! 10166: default: ! 10167: if( eType>0 ){ ! 10168: return ((eType-12) / 2); ! 10169: } ! 10170: return 0; ! 10171: } ! 10172: } ! 10173: ! 10174: /* ! 10175: ** Load a value of type eType from buffer pData and use it to set the ! 10176: ** result of context object pCtx. ! 10177: */ ! 10178: static void dbdataValue( ! 10179: sqlite3_context *pCtx, ! 10180: int eType, ! 10181: u8 *pData, ! 10182: int nData ! 10183: ){ ! 10184: if( eType>=0 && dbdataValueBytes(eType)<=nData ){ ! 10185: switch( eType ){ ! 10186: case 0: ! 10187: case 10: ! 10188: case 11: ! 10189: sqlite3_result_null(pCtx); ! 10190: break; ! 10191: ! 10192: case 8: ! 10193: sqlite3_result_int(pCtx, 0); ! 10194: break; ! 10195: case 9: ! 10196: sqlite3_result_int(pCtx, 1); ! 10197: break; ! 10198: ! 10199: case 1: case 2: case 3: case 4: case 5: case 6: case 7: { ! 10200: sqlite3_uint64 v = (signed char)pData[0]; ! 10201: pData++; ! 10202: switch( eType ){ ! 10203: case 7: ! 10204: case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; ! 10205: case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; ! 10206: case 4: v = (v<<8) + pData[0]; pData++; ! 10207: case 3: v = (v<<8) + pData[0]; pData++; ! 10208: case 2: v = (v<<8) + pData[0]; pData++; ! 10209: } ! 10210: ! 10211: if( eType==7 ){ ! 10212: double r; ! 10213: memcpy(&r, &v, sizeof(r)); ! 10214: sqlite3_result_double(pCtx, r); ! 10215: }else{ ! 10216: sqlite3_result_int64(pCtx, (sqlite3_int64)v); ! 10217: } ! 10218: break; ! 10219: } ! 10220: ! 10221: default: { ! 10222: int n = ((eType-12) / 2); ! 10223: if( eType % 2 ){ ! 10224: sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT); ! 10225: }else{ ! 10226: sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT); ! 10227: } ! 10228: } ! 10229: } ! 10230: } ! 10231: } ! 10232: ! 10233: /* ! 10234: ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry. ! 10235: */ ! 10236: static int dbdataNext(sqlite3_vtab_cursor *pCursor){ ! 10237: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10238: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; ! 10239: ! 10240: pCsr->iRowid++; ! 10241: while( 1 ){ ! 10242: int rc; ! 10243: int iOff = (pCsr->iPgno==1 ? 100 : 0); ! 10244: int bNextPage = 0; ! 10245: ! 10246: if( pCsr->aPage==0 ){ ! 10247: while( 1 ){ ! 10248: if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; ! 10249: rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); ! 10250: if( rc!=SQLITE_OK ) return rc; ! 10251: if( pCsr->aPage ) break; ! 10252: pCsr->iPgno++; ! 10253: } ! 10254: pCsr->iCell = pTab->bPtr ? -2 : 0; ! 10255: pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); ! 10256: } ! 10257: ! 10258: if( pTab->bPtr ){ ! 10259: if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ ! 10260: pCsr->iCell = pCsr->nCell; ! 10261: } ! 10262: pCsr->iCell++; ! 10263: if( pCsr->iCell>=pCsr->nCell ){ ! 10264: sqlite3_free(pCsr->aPage); ! 10265: pCsr->aPage = 0; ! 10266: if( pCsr->bOnePage ) return SQLITE_OK; ! 10267: pCsr->iPgno++; ! 10268: }else{ ! 10269: return SQLITE_OK; ! 10270: } ! 10271: }else{ ! 10272: /* If there is no record loaded, load it now. */ ! 10273: if( pCsr->pRec==0 ){ ! 10274: int bHasRowid = 0; ! 10275: int nPointer = 0; ! 10276: sqlite3_int64 nPayload = 0; ! 10277: sqlite3_int64 nHdr = 0; ! 10278: int iHdr; ! 10279: int U, X; ! 10280: int nLocal; ! 10281: ! 10282: switch( pCsr->aPage[iOff] ){ ! 10283: case 0x02: ! 10284: nPointer = 4; ! 10285: break; ! 10286: case 0x0a: ! 10287: break; ! 10288: case 0x0d: ! 10289: bHasRowid = 1; ! 10290: break; ! 10291: default: ! 10292: /* This is not a b-tree page with records on it. Continue. */ ! 10293: pCsr->iCell = pCsr->nCell; ! 10294: break; ! 10295: } ! 10296: ! 10297: if( pCsr->iCell>=pCsr->nCell ){ ! 10298: bNextPage = 1; ! 10299: }else{ ! 10300: ! 10301: iOff += 8 + nPointer + pCsr->iCell*2; ! 10302: if( iOff>pCsr->nPage ){ ! 10303: bNextPage = 1; ! 10304: }else{ ! 10305: iOff = get_uint16(&pCsr->aPage[iOff]); ! 10306: } ! 10307: ! 10308: /* For an interior node cell, skip past the child-page number */ ! 10309: iOff += nPointer; ! 10310: ! 10311: /* Load the "byte of payload including overflow" field */ ! 10312: if( bNextPage || iOff>pCsr->nPage ){ ! 10313: bNextPage = 1; ! 10314: }else{ ! 10315: iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); ! 10316: } ! 10317: ! 10318: /* If this is a leaf intkey cell, load the rowid */ ! 10319: if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){ ! 10320: iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); ! 10321: } ! 10322: ! 10323: /* Figure out how much data to read from the local page */ ! 10324: U = pCsr->nPage; ! 10325: if( bHasRowid ){ ! 10326: X = U-35; ! 10327: }else{ ! 10328: X = ((U-12)*64/255)-23; ! 10329: } ! 10330: if( nPayload<=X ){ ! 10331: nLocal = nPayload; ! 10332: }else{ ! 10333: int M, K; ! 10334: M = ((U-12)*32/255)-23; ! 10335: K = M+((nPayload-M)%(U-4)); ! 10336: if( K<=X ){ ! 10337: nLocal = K; ! 10338: }else{ ! 10339: nLocal = M; ! 10340: } ! 10341: } ! 10342: ! 10343: if( bNextPage || nLocal+iOff>pCsr->nPage ){ ! 10344: bNextPage = 1; ! 10345: }else{ ! 10346: ! 10347: /* Allocate space for payload. And a bit more to catch small buffer ! 10348: ** overruns caused by attempting to read a varint or similar from ! 10349: ** near the end of a corrupt record. */ ! 10350: pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES); ! 10351: if( pCsr->pRec==0 ) return SQLITE_NOMEM; ! 10352: memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES); ! 10353: pCsr->nRec = nPayload; ! 10354: ! 10355: /* Load the nLocal bytes of payload */ ! 10356: memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); ! 10357: iOff += nLocal; ! 10358: ! 10359: /* Load content from overflow pages */ ! 10360: if( nPayload>nLocal ){ ! 10361: sqlite3_int64 nRem = nPayload - nLocal; ! 10362: unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); ! 10363: while( nRem>0 ){ ! 10364: u8 *aOvfl = 0; ! 10365: int nOvfl = 0; ! 10366: int nCopy; ! 10367: rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); ! 10368: assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage ); ! 10369: if( rc!=SQLITE_OK ) return rc; ! 10370: if( aOvfl==0 ) break; ! 10371: ! 10372: nCopy = U-4; ! 10373: if( nCopy>nRem ) nCopy = nRem; ! 10374: memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); ! 10375: nRem -= nCopy; ! 10376: ! 10377: pgnoOvfl = get_uint32(aOvfl); ! 10378: sqlite3_free(aOvfl); ! 10379: } ! 10380: } ! 10381: ! 10382: iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); ! 10383: pCsr->nHdr = nHdr; ! 10384: pCsr->pHdrPtr = &pCsr->pRec[iHdr]; ! 10385: pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; ! 10386: pCsr->iField = (bHasRowid ? -1 : 0); ! 10387: } ! 10388: } ! 10389: }else{ ! 10390: pCsr->iField++; ! 10391: if( pCsr->iField>0 ){ ! 10392: sqlite3_int64 iType; ! 10393: if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ ! 10394: bNextPage = 1; ! 10395: }else{ ! 10396: pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType); ! 10397: pCsr->pPtr += dbdataValueBytes(iType); ! 10398: } ! 10399: } ! 10400: } ! 10401: ! 10402: if( bNextPage ){ ! 10403: sqlite3_free(pCsr->aPage); ! 10404: sqlite3_free(pCsr->pRec); ! 10405: pCsr->aPage = 0; ! 10406: pCsr->pRec = 0; ! 10407: if( pCsr->bOnePage ) return SQLITE_OK; ! 10408: pCsr->iPgno++; ! 10409: }else{ ! 10410: if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){ ! 10411: return SQLITE_OK; ! 10412: } ! 10413: ! 10414: /* Advance to the next cell. The next iteration of the loop will load ! 10415: ** the record and so on. */ ! 10416: sqlite3_free(pCsr->pRec); ! 10417: pCsr->pRec = 0; ! 10418: pCsr->iCell++; ! 10419: } ! 10420: } ! 10421: } ! 10422: ! 10423: assert( !"can't get here" ); ! 10424: return SQLITE_OK; ! 10425: } ! 10426: ! 10427: /* ! 10428: ** Return true if the cursor is at EOF. ! 10429: */ ! 10430: static int dbdataEof(sqlite3_vtab_cursor *pCursor){ ! 10431: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10432: return pCsr->aPage==0; ! 10433: } ! 10434: ! 10435: /* ! 10436: ** Determine the size in pages of database zSchema (where zSchema is ! 10437: ** "main", "temp" or the name of an attached database) and set ! 10438: ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise, ! 10439: ** an SQLite error code. ! 10440: */ ! 10441: static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){ ! 10442: DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab; ! 10443: char *zSql = 0; ! 10444: int rc, rc2; ! 10445: sqlite3_stmt *pStmt = 0; ! 10446: ! 10447: zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema); ! 10448: if( zSql==0 ) return SQLITE_NOMEM; ! 10449: rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0); ! 10450: sqlite3_free(zSql); ! 10451: if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ ! 10452: pCsr->szDb = sqlite3_column_int(pStmt, 0); ! 10453: } ! 10454: rc2 = sqlite3_finalize(pStmt); ! 10455: if( rc==SQLITE_OK ) rc = rc2; ! 10456: return rc; ! 10457: } ! 10458: ! 10459: /* ! 10460: ** xFilter method for sqlite_dbdata and sqlite_dbptr. ! 10461: */ ! 10462: static int dbdataFilter( ! 10463: sqlite3_vtab_cursor *pCursor, ! 10464: int idxNum, const char *idxStr, ! 10465: int argc, sqlite3_value **argv ! 10466: ){ ! 10467: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10468: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; ! 10469: int rc = SQLITE_OK; ! 10470: const char *zSchema = "main"; ! 10471: ! 10472: dbdataResetCursor(pCsr); ! 10473: assert( pCsr->iPgno==1 ); ! 10474: if( idxNum & 0x01 ){ ! 10475: zSchema = (const char*)sqlite3_value_text(argv[0]); ! 10476: } ! 10477: if( idxNum & 0x02 ){ ! 10478: pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]); ! 10479: pCsr->bOnePage = 1; ! 10480: }else{ ! 10481: pCsr->nPage = dbdataDbsize(pCsr, zSchema); ! 10482: rc = dbdataDbsize(pCsr, zSchema); ! 10483: } ! 10484: ! 10485: if( rc==SQLITE_OK ){ ! 10486: if( pTab->pStmt ){ ! 10487: pCsr->pStmt = pTab->pStmt; ! 10488: pTab->pStmt = 0; ! 10489: }else{ ! 10490: rc = sqlite3_prepare_v2(pTab->db, ! 10491: "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, ! 10492: &pCsr->pStmt, 0 ! 10493: ); ! 10494: } ! 10495: } ! 10496: if( rc==SQLITE_OK ){ ! 10497: rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); ! 10498: }else{ ! 10499: pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); ! 10500: } ! 10501: if( rc==SQLITE_OK ){ ! 10502: rc = dbdataNext(pCursor); ! 10503: } ! 10504: return rc; ! 10505: } ! 10506: ! 10507: /* ! 10508: ** Return a column for the sqlite_dbdata or sqlite_dbptr table. ! 10509: */ ! 10510: static int dbdataColumn( ! 10511: sqlite3_vtab_cursor *pCursor, ! 10512: sqlite3_context *ctx, ! 10513: int i ! 10514: ){ ! 10515: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10516: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; ! 10517: if( pTab->bPtr ){ ! 10518: switch( i ){ ! 10519: case DBPTR_COLUMN_PGNO: ! 10520: sqlite3_result_int64(ctx, pCsr->iPgno); ! 10521: break; ! 10522: case DBPTR_COLUMN_CHILD: { ! 10523: int iOff = pCsr->iPgno==1 ? 100 : 0; ! 10524: if( pCsr->iCell<0 ){ ! 10525: iOff += 8; ! 10526: }else{ ! 10527: iOff += 12 + pCsr->iCell*2; ! 10528: if( iOff>pCsr->nPage ) return SQLITE_OK; ! 10529: iOff = get_uint16(&pCsr->aPage[iOff]); ! 10530: } ! 10531: if( iOff<=pCsr->nPage ){ ! 10532: sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff])); ! 10533: } ! 10534: break; ! 10535: } ! 10536: } ! 10537: }else{ ! 10538: switch( i ){ ! 10539: case DBDATA_COLUMN_PGNO: ! 10540: sqlite3_result_int64(ctx, pCsr->iPgno); ! 10541: break; ! 10542: case DBDATA_COLUMN_CELL: ! 10543: sqlite3_result_int(ctx, pCsr->iCell); ! 10544: break; ! 10545: case DBDATA_COLUMN_FIELD: ! 10546: sqlite3_result_int(ctx, pCsr->iField); ! 10547: break; ! 10548: case DBDATA_COLUMN_VALUE: { ! 10549: if( pCsr->iField<0 ){ ! 10550: sqlite3_result_int64(ctx, pCsr->iIntkey); ! 10551: }else{ ! 10552: sqlite3_int64 iType; ! 10553: dbdataGetVarint(pCsr->pHdrPtr, &iType); ! 10554: dbdataValue( ! 10555: ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr ! 10556: ); ! 10557: } ! 10558: break; ! 10559: } ! 10560: } ! 10561: } ! 10562: return SQLITE_OK; ! 10563: } ! 10564: ! 10565: /* ! 10566: ** Return the rowid for an sqlite_dbdata or sqlite_dptr table. ! 10567: */ ! 10568: static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ ! 10569: DbdataCursor *pCsr = (DbdataCursor*)pCursor; ! 10570: *pRowid = pCsr->iRowid; ! 10571: return SQLITE_OK; ! 10572: } ! 10573: ! 10574: ! 10575: /* ! 10576: ** Invoke this routine to register the "sqlite_dbdata" virtual table module ! 10577: */ ! 10578: static int sqlite3DbdataRegister(sqlite3 *db){ ! 10579: static sqlite3_module dbdata_module = { ! 10580: 0, /* iVersion */ ! 10581: 0, /* xCreate */ ! 10582: dbdataConnect, /* xConnect */ ! 10583: dbdataBestIndex, /* xBestIndex */ ! 10584: dbdataDisconnect, /* xDisconnect */ ! 10585: 0, /* xDestroy */ ! 10586: dbdataOpen, /* xOpen - open a cursor */ ! 10587: dbdataClose, /* xClose - close a cursor */ ! 10588: dbdataFilter, /* xFilter - configure scan constraints */ ! 10589: dbdataNext, /* xNext - advance a cursor */ ! 10590: dbdataEof, /* xEof - check for end of scan */ ! 10591: dbdataColumn, /* xColumn - read data */ ! 10592: dbdataRowid, /* xRowid - read data */ ! 10593: 0, /* xUpdate */ ! 10594: 0, /* xBegin */ ! 10595: 0, /* xSync */ ! 10596: 0, /* xCommit */ ! 10597: 0, /* xRollback */ ! 10598: 0, /* xFindMethod */ ! 10599: 0, /* xRename */ ! 10600: 0, /* xSavepoint */ ! 10601: 0, /* xRelease */ ! 10602: 0, /* xRollbackTo */ ! 10603: 0 /* xShadowName */ ! 10604: }; ! 10605: ! 10606: int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0); ! 10607: if( rc==SQLITE_OK ){ ! 10608: rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1); ! 10609: } ! 10610: return rc; ! 10611: } ! 10612: ! 10613: #ifdef _WIN32 ! 10614: ! 10615: #endif ! 10616: int sqlite3_dbdata_init( ! 10617: sqlite3 *db, ! 10618: char **pzErrMsg, ! 10619: const sqlite3_api_routines *pApi ! 10620: ){ ! 10621: SQLITE_EXTENSION_INIT2(pApi); ! 10622: return sqlite3DbdataRegister(db); ! 10623: } ! 10624: ! 10625: /************************* End ../ext/misc/dbdata.c ********************/ ! 10626: #endif ! 10627: ! 10628: #if defined(SQLITE_ENABLE_SESSION) ! 10629: /* ! 10630: ** State information for a single open session ! 10631: */ ! 10632: typedef struct OpenSession OpenSession; ! 10633: struct OpenSession { ! 10634: char *zName; /* Symbolic name for this session */ ! 10635: int nFilter; /* Number of xFilter rejection GLOB patterns */ ! 10636: char **azFilter; /* Array of xFilter rejection GLOB patterns */ ! 10637: sqlite3_session *p; /* The open session */ ! 10638: }; ! 10639: #endif ! 10640: ! 10641: typedef struct ExpertInfo ExpertInfo; ! 10642: struct ExpertInfo { ! 10643: sqlite3expert *pExpert; ! 10644: int bVerbose; ! 10645: }; ! 10646: ! 10647: /* A single line in the EQP output */ ! 10648: typedef struct EQPGraphRow EQPGraphRow; ! 10649: struct EQPGraphRow { ! 10650: int iEqpId; /* ID for this row */ ! 10651: int iParentId; /* ID of the parent row */ ! 10652: EQPGraphRow *pNext; /* Next row in sequence */ ! 10653: char zText[1]; /* Text to display for this row */ ! 10654: }; ! 10655: ! 10656: /* All EQP output is collected into an instance of the following */ ! 10657: typedef struct EQPGraph EQPGraph; ! 10658: struct EQPGraph { ! 10659: EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ ! 10660: EQPGraphRow *pLast; /* Last element of the pRow list */ ! 10661: char zPrefix[100]; /* Graph prefix */ ! 10662: }; ! 10663: ! 10664: /* ! 10665: ** State information about the database connection is contained in an ! 10666: ** instance of the following structure. ! 10667: */ ! 10668: typedef struct ShellState ShellState; ! 10669: struct ShellState { ! 10670: sqlite3 *db; /* The database */ ! 10671: u8 autoExplain; /* Automatically turn on .explain mode */ ! 10672: u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ ! 10673: u8 autoEQPtest; /* autoEQP is in test mode */ ! 10674: u8 autoEQPtrace; /* autoEQP is in trace mode */ ! 10675: u8 statsOn; /* True to display memory stats before each finalize */ ! 10676: u8 scanstatsOn; /* True to display scan stats before each finalize */ ! 10677: u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ ! 10678: u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ ! 10679: u8 nEqpLevel; /* Depth of the EQP output graph */ ! 10680: u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ ! 10681: unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ ! 10682: int outCount; /* Revert to stdout when reaching zero */ ! 10683: int cnt; /* Number of records displayed so far */ ! 10684: int lineno; /* Line number of last line read from in */ ! 10685: int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ ! 10686: FILE *in; /* Read commands from this stream */ ! 10687: FILE *out; /* Write results here */ ! 10688: FILE *traceOut; /* Output for sqlite3_trace() */ ! 10689: int nErr; /* Number of errors seen */ ! 10690: int mode; /* An output mode setting */ ! 10691: int modePrior; /* Saved mode */ ! 10692: int cMode; /* temporary output mode for the current query */ ! 10693: int normalMode; /* Output mode before ".explain on" */ ! 10694: int writableSchema; /* True if PRAGMA writable_schema=ON */ ! 10695: int showHeader; /* True to show column names in List or Column mode */ ! 10696: int nCheck; /* Number of ".check" commands run */ ! 10697: unsigned nProgress; /* Number of progress callbacks encountered */ ! 10698: unsigned mxProgress; /* Maximum progress callbacks before failing */ ! 10699: unsigned flgProgress; /* Flags for the progress callback */ ! 10700: unsigned shellFlgs; /* Various flags */ ! 10701: unsigned priorShFlgs; /* Saved copy of flags */ ! 10702: sqlite3_int64 szMax; /* --maxsize argument to .open */ ! 10703: char *zDestTable; /* Name of destination table when MODE_Insert */ ! 10704: char *zTempFile; /* Temporary file that might need deleting */ ! 10705: char zTestcase[30]; /* Name of current test case */ ! 10706: char colSeparator[20]; /* Column separator character for several modes */ ! 10707: char rowSeparator[20]; /* Row separator character for MODE_Ascii */ ! 10708: char colSepPrior[20]; /* Saved column separator */ ! 10709: char rowSepPrior[20]; /* Saved row separator */ ! 10710: int *colWidth; /* Requested width of each column in columnar modes */ ! 10711: int *actualWidth; /* Actual width of each column */ ! 10712: int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ ! 10713: char nullValue[20]; /* The text to print when a NULL comes back from ! 10714: ** the database */ ! 10715: char outfile[FILENAME_MAX]; /* Filename for *out */ ! 10716: const char *zDbFilename; /* name of the database file */ ! 10717: char *zFreeOnClose; /* Filename to free when closing */ ! 10718: const char *zVfs; /* Name of VFS to use */ ! 10719: sqlite3_stmt *pStmt; /* Current statement if any. */ ! 10720: FILE *pLog; /* Write log output here */ ! 10721: int *aiIndent; /* Array of indents used in MODE_Explain */ ! 10722: int nIndent; /* Size of array aiIndent[] */ ! 10723: int iIndent; /* Index of current op in aiIndent[] */ ! 10724: EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ ! 10725: #if defined(SQLITE_ENABLE_SESSION) ! 10726: int nSession; /* Number of active sessions */ ! 10727: OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ ! 10728: #endif ! 10729: ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ ! 10730: }; ! 10731: ! 10732: ! 10733: /* Allowed values for ShellState.autoEQP ! 10734: */ ! 10735: #define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ ! 10736: #define AUTOEQP_on 1 /* Automatic EQP is on */ ! 10737: #define AUTOEQP_trigger 2 /* On and also show plans for triggers */ ! 10738: #define AUTOEQP_full 3 /* Show full EXPLAIN */ ! 10739: ! 10740: /* Allowed values for ShellState.openMode ! 10741: */ ! 10742: #define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ ! 10743: #define SHELL_OPEN_NORMAL 1 /* Normal database file */ ! 10744: #define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ ! 10745: #define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ ! 10746: #define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ ! 10747: #define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ ! 10748: #define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */ ! 10749: ! 10750: /* Allowed values for ShellState.eTraceType ! 10751: */ ! 10752: #define SHELL_TRACE_PLAIN 0 /* Show input SQL text */ ! 10753: #define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */ ! 10754: #define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */ ! 10755: ! 10756: /* Bits in the ShellState.flgProgress variable */ ! 10757: #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */ ! 10758: #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres ! 10759: ** callback limit is reached, and for each ! 10760: ** top-level SQL statement */ ! 10761: #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */ ! 10762: ! 10763: /* ! 10764: ** These are the allowed shellFlgs values ! 10765: */ ! 10766: #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */ ! 10767: #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ ! 10768: #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ ! 10769: #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ ! 10770: #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ ! 10771: #define SHFLG_CountChanges 0x00000020 /* .changes setting */ ! 10772: #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */ ! 10773: #define SHFLG_HeaderSet 0x00000080 /* .header has been used */ ! 10774: ! 10775: /* ! 10776: ** Macros for testing and setting shellFlgs ! 10777: */ ! 10778: #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0) ! 10779: #define ShellSetFlag(P,X) ((P)->shellFlgs|=(X)) ! 10780: #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) ! 10781: ! 10782: /* ! 10783: ** These are the allowed modes. ! 10784: */ ! 10785: #define MODE_Line 0 /* One column per line. Blank line between records */ ! 10786: #define MODE_Column 1 /* One record per line in neat columns */ ! 10787: #define MODE_List 2 /* One record per line with a separator */ ! 10788: #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ ! 10789: #define MODE_Html 4 /* Generate an XHTML table */ ! 10790: #define MODE_Insert 5 /* Generate SQL "insert" statements */ ! 10791: #define MODE_Quote 6 /* Quote values as for SQL */ ! 10792: #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ ! 10793: #define MODE_Csv 8 /* Quote strings, numbers are plain */ ! 10794: #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ ! 10795: #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ ! 10796: #define MODE_Pretty 11 /* Pretty-print schemas */ ! 10797: #define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */ ! 10798: #define MODE_Json 13 /* Output JSON */ ! 10799: #define MODE_Markdown 14 /* Markdown formatting */ ! 10800: #define MODE_Table 15 /* MySQL-style table formatting */ ! 10801: #define MODE_Box 16 /* Unicode box-drawing characters */ ! 10802: ! 10803: static const char *modeDescr[] = { ! 10804: "line", ! 10805: "column", ! 10806: "list", ! 10807: "semi", ! 10808: "html", ! 10809: "insert", ! 10810: "quote", ! 10811: "tcl", ! 10812: "csv", ! 10813: "explain", ! 10814: "ascii", ! 10815: "prettyprint", ! 10816: "eqp", ! 10817: "json", ! 10818: "markdown", ! 10819: "table", ! 10820: "box" ! 10821: }; ! 10822: ! 10823: /* ! 10824: ** These are the column/row/line separators used by the various ! 10825: ** import/export modes. ! 10826: */ ! 10827: #define SEP_Column "|" ! 10828: #define SEP_Row "\n" ! 10829: #define SEP_Tab "\t" ! 10830: #define SEP_Space " " ! 10831: #define SEP_Comma "," ! 10832: #define SEP_CrLf "\r\n" ! 10833: #define SEP_Unit "\x1F" ! 10834: #define SEP_Record "\x1E" ! 10835: ! 10836: /* ! 10837: ** A callback for the sqlite3_log() interface. ! 10838: */ ! 10839: static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ! 10840: ShellState *p = (ShellState*)pArg; ! 10841: if( p->pLog==0 ) return; ! 10842: utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); ! 10843: fflush(p->pLog); ! 10844: } ! 10845: ! 10846: /* ! 10847: ** SQL function: shell_putsnl(X) ! 10848: ** ! 10849: ** Write the text X to the screen (or whatever output is being directed) ! 10850: ** adding a newline at the end, and then return X. ! 10851: */ ! 10852: static void shellPutsFunc( ! 10853: sqlite3_context *pCtx, ! 10854: int nVal, ! 10855: sqlite3_value **apVal ! 10856: ){ ! 10857: ShellState *p = (ShellState*)sqlite3_user_data(pCtx); ! 10858: (void)nVal; ! 10859: utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); ! 10860: sqlite3_result_value(pCtx, apVal[0]); ! 10861: } ! 10862: ! 10863: /* ! 10864: ** SQL function: edit(VALUE) ! 10865: ** edit(VALUE,EDITOR) ! 10866: ** ! 10867: ** These steps: ! 10868: ** ! 10869: ** (1) Write VALUE into a temporary file. ! 10870: ** (2) Run program EDITOR on that temporary file. ! 10871: ** (3) Read the temporary file back and return its content as the result. ! 10872: ** (4) Delete the temporary file ! 10873: ** ! 10874: ** If the EDITOR argument is omitted, use the value in the VISUAL ! 10875: ** environment variable. If still there is no EDITOR, through an error. ! 10876: ** ! 10877: ** Also throw an error if the EDITOR program returns a non-zero exit code. ! 10878: */ ! 10879: #ifndef SQLITE_NOHAVE_SYSTEM ! 10880: static void editFunc( ! 10881: sqlite3_context *context, ! 10882: int argc, ! 10883: sqlite3_value **argv ! 10884: ){ ! 10885: const char *zEditor; ! 10886: char *zTempFile = 0; ! 10887: sqlite3 *db; ! 10888: char *zCmd = 0; ! 10889: int bBin; ! 10890: int rc; ! 10891: int hasCRNL = 0; ! 10892: FILE *f = 0; ! 10893: sqlite3_int64 sz; ! 10894: sqlite3_int64 x; ! 10895: unsigned char *p = 0; ! 10896: ! 10897: if( argc==2 ){ ! 10898: zEditor = (const char*)sqlite3_value_text(argv[1]); ! 10899: }else{ ! 10900: zEditor = getenv("VISUAL"); ! 10901: } ! 10902: if( zEditor==0 ){ ! 10903: sqlite3_result_error(context, "no editor for edit()", -1); ! 10904: return; ! 10905: } ! 10906: if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ ! 10907: sqlite3_result_error(context, "NULL input to edit()", -1); ! 10908: return; ! 10909: } ! 10910: db = sqlite3_context_db_handle(context); ! 10911: zTempFile = 0; ! 10912: sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile); ! 10913: if( zTempFile==0 ){ ! 10914: sqlite3_uint64 r = 0; ! 10915: sqlite3_randomness(sizeof(r), &r); ! 10916: zTempFile = sqlite3_mprintf("temp%llx", r); ! 10917: if( zTempFile==0 ){ ! 10918: sqlite3_result_error_nomem(context); ! 10919: return; ! 10920: } ! 10921: } ! 10922: bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; ! 10923: /* When writing the file to be edited, do \n to \r\n conversions on systems ! 10924: ** that want \r\n line endings */ ! 10925: f = fopen(zTempFile, bBin ? "wb" : "w"); ! 10926: if( f==0 ){ ! 10927: sqlite3_result_error(context, "edit() cannot open temp file", -1); ! 10928: goto edit_func_end; ! 10929: } ! 10930: sz = sqlite3_value_bytes(argv[0]); ! 10931: if( bBin ){ ! 10932: x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f); ! 10933: }else{ ! 10934: const char *z = (const char*)sqlite3_value_text(argv[0]); ! 10935: /* Remember whether or not the value originally contained \r\n */ ! 10936: if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; ! 10937: x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f); ! 10938: } ! 10939: fclose(f); ! 10940: f = 0; ! 10941: if( x!=sz ){ ! 10942: sqlite3_result_error(context, "edit() could not write the whole file", -1); ! 10943: goto edit_func_end; ! 10944: } ! 10945: zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile); ! 10946: if( zCmd==0 ){ ! 10947: sqlite3_result_error_nomem(context); ! 10948: goto edit_func_end; ! 10949: } ! 10950: rc = system(zCmd); ! 10951: sqlite3_free(zCmd); ! 10952: if( rc ){ ! 10953: sqlite3_result_error(context, "EDITOR returned non-zero", -1); ! 10954: goto edit_func_end; ! 10955: } ! 10956: f = fopen(zTempFile, "rb"); ! 10957: if( f==0 ){ ! 10958: sqlite3_result_error(context, ! 10959: "edit() cannot reopen temp file after edit", -1); ! 10960: goto edit_func_end; ! 10961: } ! 10962: fseek(f, 0, SEEK_END); ! 10963: sz = ftell(f); ! 10964: rewind(f); ! 10965: p = sqlite3_malloc64( sz+1 ); ! 10966: if( p==0 ){ ! 10967: sqlite3_result_error_nomem(context); ! 10968: goto edit_func_end; ! 10969: } ! 10970: x = fread(p, 1, (size_t)sz, f); ! 10971: fclose(f); ! 10972: f = 0; ! 10973: if( x!=sz ){ ! 10974: sqlite3_result_error(context, "could not read back the whole file", -1); ! 10975: goto edit_func_end; ! 10976: } ! 10977: if( bBin ){ ! 10978: sqlite3_result_blob64(context, p, sz, sqlite3_free); ! 10979: }else{ ! 10980: sqlite3_int64 i, j; ! 10981: if( hasCRNL ){ ! 10982: /* If the original contains \r\n then do no conversions back to \n */ ! 10983: j = sz; ! 10984: }else{ ! 10985: /* If the file did not originally contain \r\n then convert any new ! 10986: ** \r\n back into \n */ ! 10987: for(i=j=0; i<sz; i++){ ! 10988: if( p[i]=='\r' && p[i+1]=='\n' ) i++; ! 10989: p[j++] = p[i]; ! 10990: } ! 10991: sz = j; ! 10992: p[sz] = 0; ! 10993: } ! 10994: sqlite3_result_text64(context, (const char*)p, sz, ! 10995: sqlite3_free, SQLITE_UTF8); ! 10996: } ! 10997: p = 0; ! 10998: ! 10999: edit_func_end: ! 11000: if( f ) fclose(f); ! 11001: unlink(zTempFile); ! 11002: sqlite3_free(zTempFile); ! 11003: sqlite3_free(p); ! 11004: } ! 11005: #endif /* SQLITE_NOHAVE_SYSTEM */ ! 11006: ! 11007: /* ! 11008: ** Save or restore the current output mode ! 11009: */ ! 11010: static void outputModePush(ShellState *p){ ! 11011: p->modePrior = p->mode; ! 11012: p->priorShFlgs = p->shellFlgs; ! 11013: memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); ! 11014: memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); ! 11015: } ! 11016: static void outputModePop(ShellState *p){ ! 11017: p->mode = p->modePrior; ! 11018: p->shellFlgs = p->priorShFlgs; ! 11019: memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); ! 11020: memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); ! 11021: } ! 11022: ! 11023: /* ! 11024: ** Output the given string as a hex-encoded blob (eg. X'1234' ) ! 11025: */ ! 11026: static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ ! 11027: int i; ! 11028: char *zBlob = (char *)pBlob; ! 11029: raw_printf(out,"X'"); ! 11030: for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); } ! 11031: raw_printf(out,"'"); ! 11032: } ! 11033: ! 11034: /* ! 11035: ** Find a string that is not found anywhere in z[]. Return a pointer ! 11036: ** to that string. ! 11037: ** ! 11038: ** Try to use zA and zB first. If both of those are already found in z[] ! 11039: ** then make up some string and store it in the buffer zBuf. ! 11040: */ ! 11041: static const char *unused_string( ! 11042: const char *z, /* Result must not appear anywhere in z */ ! 11043: const char *zA, const char *zB, /* Try these first */ ! 11044: char *zBuf /* Space to store a generated string */ ! 11045: ){ ! 11046: unsigned i = 0; ! 11047: if( strstr(z, zA)==0 ) return zA; ! 11048: if( strstr(z, zB)==0 ) return zB; ! 11049: do{ ! 11050: sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++); ! 11051: }while( strstr(z,zBuf)!=0 ); ! 11052: return zBuf; ! 11053: } ! 11054: ! 11055: /* ! 11056: ** Output the given string as a quoted string using SQL quoting conventions. ! 11057: ** ! 11058: ** See also: output_quoted_escaped_string() ! 11059: */ ! 11060: static void output_quoted_string(FILE *out, const char *z){ ! 11061: int i; ! 11062: char c; ! 11063: setBinaryMode(out, 1); ! 11064: for(i=0; (c = z[i])!=0 && c!='\''; i++){} ! 11065: if( c==0 ){ ! 11066: utf8_printf(out,"'%s'",z); ! 11067: }else{ ! 11068: raw_printf(out, "'"); ! 11069: while( *z ){ ! 11070: for(i=0; (c = z[i])!=0 && c!='\''; i++){} ! 11071: if( c=='\'' ) i++; ! 11072: if( i ){ ! 11073: utf8_printf(out, "%.*s", i, z); ! 11074: z += i; ! 11075: } ! 11076: if( c=='\'' ){ ! 11077: raw_printf(out, "'"); ! 11078: continue; ! 11079: } ! 11080: if( c==0 ){ ! 11081: break; ! 11082: } ! 11083: z++; ! 11084: } ! 11085: raw_printf(out, "'"); ! 11086: } ! 11087: setTextMode(out, 1); ! 11088: } ! 11089: ! 11090: /* ! 11091: ** Output the given string as a quoted string using SQL quoting conventions. ! 11092: ** Additionallly , escape the "\n" and "\r" characters so that they do not ! 11093: ** get corrupted by end-of-line translation facilities in some operating ! 11094: ** systems. ! 11095: ** ! 11096: ** This is like output_quoted_string() but with the addition of the \r\n ! 11097: ** escape mechanism. ! 11098: */ ! 11099: static void output_quoted_escaped_string(FILE *out, const char *z){ ! 11100: int i; ! 11101: char c; ! 11102: setBinaryMode(out, 1); ! 11103: for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} ! 11104: if( c==0 ){ ! 11105: utf8_printf(out,"'%s'",z); ! 11106: }else{ ! 11107: const char *zNL = 0; ! 11108: const char *zCR = 0; ! 11109: int nNL = 0; ! 11110: int nCR = 0; ! 11111: char zBuf1[20], zBuf2[20]; ! 11112: for(i=0; z[i]; i++){ ! 11113: if( z[i]=='\n' ) nNL++; ! 11114: if( z[i]=='\r' ) nCR++; ! 11115: } ! 11116: if( nNL ){ ! 11117: raw_printf(out, "replace("); ! 11118: zNL = unused_string(z, "\\n", "\\012", zBuf1); ! 11119: } ! 11120: if( nCR ){ ! 11121: raw_printf(out, "replace("); ! 11122: zCR = unused_string(z, "\\r", "\\015", zBuf2); ! 11123: } ! 11124: raw_printf(out, "'"); ! 11125: while( *z ){ ! 11126: for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){} ! 11127: if( c=='\'' ) i++; ! 11128: if( i ){ ! 11129: utf8_printf(out, "%.*s", i, z); ! 11130: z += i; ! 11131: } ! 11132: if( c=='\'' ){ ! 11133: raw_printf(out, "'"); ! 11134: continue; ! 11135: } ! 11136: if( c==0 ){ ! 11137: break; ! 11138: } ! 11139: z++; ! 11140: if( c=='\n' ){ ! 11141: raw_printf(out, "%s", zNL); ! 11142: continue; ! 11143: } ! 11144: raw_printf(out, "%s", zCR); ! 11145: } ! 11146: raw_printf(out, "'"); ! 11147: if( nCR ){ ! 11148: raw_printf(out, ",'%s',char(13))", zCR); ! 11149: } ! 11150: if( nNL ){ ! 11151: raw_printf(out, ",'%s',char(10))", zNL); ! 11152: } ! 11153: } ! 11154: setTextMode(out, 1); ! 11155: } ! 11156: ! 11157: /* ! 11158: ** Output the given string as a quoted according to C or TCL quoting rules. ! 11159: */ ! 11160: static void output_c_string(FILE *out, const char *z){ ! 11161: unsigned int c; ! 11162: fputc('"', out); ! 11163: while( (c = *(z++))!=0 ){ ! 11164: if( c=='\\' ){ ! 11165: fputc(c, out); ! 11166: fputc(c, out); ! 11167: }else if( c=='"' ){ ! 11168: fputc('\\', out); ! 11169: fputc('"', out); ! 11170: }else if( c=='\t' ){ ! 11171: fputc('\\', out); ! 11172: fputc('t', out); ! 11173: }else if( c=='\n' ){ ! 11174: fputc('\\', out); ! 11175: fputc('n', out); ! 11176: }else if( c=='\r' ){ ! 11177: fputc('\\', out); ! 11178: fputc('r', out); ! 11179: }else if( !isprint(c&0xff) ){ ! 11180: raw_printf(out, "\\%03o", c&0xff); ! 11181: }else{ ! 11182: fputc(c, out); ! 11183: } ! 11184: } ! 11185: fputc('"', out); ! 11186: } ! 11187: ! 11188: /* ! 11189: ** Output the given string as a quoted according to JSON quoting rules. ! 11190: */ ! 11191: static void output_json_string(FILE *out, const char *z, int n){ ! 11192: unsigned int c; ! 11193: if( n<0 ) n = (int)strlen(z); ! 11194: fputc('"', out); ! 11195: while( n-- ){ ! 11196: c = *(z++); ! 11197: if( c=='\\' || c=='"' ){ ! 11198: fputc('\\', out); ! 11199: fputc(c, out); ! 11200: }else if( c<=0x1f ){ ! 11201: fputc('\\', out); ! 11202: if( c=='\b' ){ ! 11203: fputc('b', out); ! 11204: }else if( c=='\f' ){ ! 11205: fputc('f', out); ! 11206: }else if( c=='\n' ){ ! 11207: fputc('n', out); ! 11208: }else if( c=='\r' ){ ! 11209: fputc('r', out); ! 11210: }else if( c=='\t' ){ ! 11211: fputc('t', out); ! 11212: }else{ ! 11213: raw_printf(out, "u%04x",c); ! 11214: } ! 11215: }else{ ! 11216: fputc(c, out); ! 11217: } ! 11218: } ! 11219: fputc('"', out); ! 11220: } ! 11221: ! 11222: /* ! 11223: ** Output the given string with characters that are special to ! 11224: ** HTML escaped. ! 11225: */ ! 11226: static void output_html_string(FILE *out, const char *z){ ! 11227: int i; ! 11228: if( z==0 ) z = ""; ! 11229: while( *z ){ ! 11230: for(i=0; z[i] ! 11231: && z[i]!='<' ! 11232: && z[i]!='&' ! 11233: && z[i]!='>' ! 11234: && z[i]!='\"' ! 11235: && z[i]!='\''; ! 11236: i++){} ! 11237: if( i>0 ){ ! 11238: utf8_printf(out,"%.*s",i,z); ! 11239: } ! 11240: if( z[i]=='<' ){ ! 11241: raw_printf(out,"<"); ! 11242: }else if( z[i]=='&' ){ ! 11243: raw_printf(out,"&"); ! 11244: }else if( z[i]=='>' ){ ! 11245: raw_printf(out,">"); ! 11246: }else if( z[i]=='\"' ){ ! 11247: raw_printf(out,"""); ! 11248: }else if( z[i]=='\'' ){ ! 11249: raw_printf(out,"'"); ! 11250: }else{ ! 11251: break; ! 11252: } ! 11253: z += i + 1; ! 11254: } ! 11255: } ! 11256: ! 11257: /* ! 11258: ** If a field contains any character identified by a 1 in the following ! 11259: ** array, then the string must be quoted for CSV. ! 11260: */ ! 11261: static const char needCsvQuote[] = { ! 11262: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11263: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11264: 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ! 11265: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 11266: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 11267: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 11268: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 11269: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ! 11270: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11271: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11272: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11273: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11274: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11275: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11276: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11277: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 11278: }; ! 11279: ! 11280: /* ! 11281: ** Output a single term of CSV. Actually, p->colSeparator is used for ! 11282: ** the separator, which may or may not be a comma. p->nullValue is ! 11283: ** the null value. Strings are quoted if necessary. The separator ! 11284: ** is only issued if bSep is true. ! 11285: */ ! 11286: static void output_csv(ShellState *p, const char *z, int bSep){ ! 11287: FILE *out = p->out; ! 11288: if( z==0 ){ ! 11289: utf8_printf(out,"%s",p->nullValue); ! 11290: }else{ ! 11291: int i; ! 11292: int nSep = strlen30(p->colSeparator); ! 11293: for(i=0; z[i]; i++){ ! 11294: if( needCsvQuote[((unsigned char*)z)[i]] ! 11295: || (z[i]==p->colSeparator[0] && ! 11296: (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){ ! 11297: i = 0; ! 11298: break; ! 11299: } ! 11300: } ! 11301: if( i==0 ){ ! 11302: char *zQuoted = sqlite3_mprintf("\"%w\"", z); ! 11303: utf8_printf(out, "%s", zQuoted); ! 11304: sqlite3_free(zQuoted); ! 11305: }else{ ! 11306: utf8_printf(out, "%s", z); ! 11307: } ! 11308: } ! 11309: if( bSep ){ ! 11310: utf8_printf(p->out, "%s", p->colSeparator); ! 11311: } ! 11312: } ! 11313: ! 11314: /* ! 11315: ** This routine runs when the user presses Ctrl-C ! 11316: */ ! 11317: static void interrupt_handler(int NotUsed){ ! 11318: UNUSED_PARAMETER(NotUsed); ! 11319: seenInterrupt++; ! 11320: if( seenInterrupt>2 ) exit(1); ! 11321: if( globalDb ) sqlite3_interrupt(globalDb); ! 11322: } ! 11323: ! 11324: #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) ! 11325: /* ! 11326: ** This routine runs for console events (e.g. Ctrl-C) on Win32 ! 11327: */ ! 11328: static BOOL WINAPI ConsoleCtrlHandler( ! 11329: DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */ ! 11330: ){ ! 11331: if( dwCtrlType==CTRL_C_EVENT ){ ! 11332: interrupt_handler(0); ! 11333: return TRUE; ! 11334: } ! 11335: return FALSE; ! 11336: } ! 11337: #endif ! 11338: ! 11339: #ifndef SQLITE_OMIT_AUTHORIZATION ! 11340: /* ! 11341: ** When the ".auth ON" is set, the following authorizer callback is ! 11342: ** invoked. It always returns SQLITE_OK. ! 11343: */ ! 11344: static int shellAuth( ! 11345: void *pClientData, ! 11346: int op, ! 11347: const char *zA1, ! 11348: const char *zA2, ! 11349: const char *zA3, ! 11350: const char *zA4 ! 11351: ){ ! 11352: ShellState *p = (ShellState*)pClientData; ! 11353: static const char *azAction[] = { 0, ! 11354: "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX", ! 11355: "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW", ! 11356: "CREATE_TRIGGER", "CREATE_VIEW", "DELETE", ! 11357: "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX", ! 11358: "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW", ! 11359: "DROP_TRIGGER", "DROP_VIEW", "INSERT", ! 11360: "PRAGMA", "READ", "SELECT", ! 11361: "TRANSACTION", "UPDATE", "ATTACH", ! 11362: "DETACH", "ALTER_TABLE", "REINDEX", ! 11363: "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE", ! 11364: "FUNCTION", "SAVEPOINT", "RECURSIVE" ! 11365: }; ! 11366: int i; ! 11367: const char *az[4]; ! 11368: az[0] = zA1; ! 11369: az[1] = zA2; ! 11370: az[2] = zA3; ! 11371: az[3] = zA4; ! 11372: utf8_printf(p->out, "authorizer: %s", azAction[op]); ! 11373: for(i=0; i<4; i++){ ! 11374: raw_printf(p->out, " "); ! 11375: if( az[i] ){ ! 11376: output_c_string(p->out, az[i]); ! 11377: }else{ ! 11378: raw_printf(p->out, "NULL"); ! 11379: } ! 11380: } ! 11381: raw_printf(p->out, "\n"); ! 11382: return SQLITE_OK; ! 11383: } ! 11384: #endif ! 11385: ! 11386: /* ! 11387: ** Print a schema statement. Part of MODE_Semi and MODE_Pretty output. ! 11388: ** ! 11389: ** This routine converts some CREATE TABLE statements for shadow tables ! 11390: ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements. ! 11391: */ ! 11392: static void printSchemaLine(FILE *out, const char *z, const char *zTail){ ! 11393: if( z==0 ) return; ! 11394: if( zTail==0 ) return; ! 11395: if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ ! 11396: utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); ! 11397: }else{ ! 11398: utf8_printf(out, "%s%s", z, zTail); ! 11399: } ! 11400: } ! 11401: static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ ! 11402: char c = z[n]; ! 11403: z[n] = 0; ! 11404: printSchemaLine(out, z, zTail); ! 11405: z[n] = c; ! 11406: } ! 11407: ! 11408: /* ! 11409: ** Return true if string z[] has nothing but whitespace and comments to the ! 11410: ** end of the first line. ! 11411: */ ! 11412: static int wsToEol(const char *z){ ! 11413: int i; ! 11414: for(i=0; z[i]; i++){ ! 11415: if( z[i]=='\n' ) return 1; ! 11416: if( IsSpace(z[i]) ) continue; ! 11417: if( z[i]=='-' && z[i+1]=='-' ) return 1; ! 11418: return 0; ! 11419: } ! 11420: return 1; ! 11421: } ! 11422: ! 11423: /* ! 11424: ** Add a new entry to the EXPLAIN QUERY PLAN data ! 11425: */ ! 11426: static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ ! 11427: EQPGraphRow *pNew; ! 11428: int nText = strlen30(zText); ! 11429: if( p->autoEQPtest ){ ! 11430: utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); ! 11431: } ! 11432: pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); ! 11433: if( pNew==0 ) shell_out_of_memory(); ! 11434: pNew->iEqpId = iEqpId; ! 11435: pNew->iParentId = p2; ! 11436: memcpy(pNew->zText, zText, nText+1); ! 11437: pNew->pNext = 0; ! 11438: if( p->sGraph.pLast ){ ! 11439: p->sGraph.pLast->pNext = pNew; ! 11440: }else{ ! 11441: p->sGraph.pRow = pNew; ! 11442: } ! 11443: p->sGraph.pLast = pNew; ! 11444: } ! 11445: ! 11446: /* ! 11447: ** Free and reset the EXPLAIN QUERY PLAN data that has been collected ! 11448: ** in p->sGraph. ! 11449: */ ! 11450: static void eqp_reset(ShellState *p){ ! 11451: EQPGraphRow *pRow, *pNext; ! 11452: for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ ! 11453: pNext = pRow->pNext; ! 11454: sqlite3_free(pRow); ! 11455: } ! 11456: memset(&p->sGraph, 0, sizeof(p->sGraph)); ! 11457: } ! 11458: ! 11459: /* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after ! 11460: ** pOld, or return the first such line if pOld is NULL ! 11461: */ ! 11462: static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ ! 11463: EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; ! 11464: while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; ! 11465: return pRow; ! 11466: } ! 11467: ! 11468: /* Render a single level of the graph that has iEqpId as its parent. Called ! 11469: ** recursively to render sublevels. ! 11470: */ ! 11471: static void eqp_render_level(ShellState *p, int iEqpId){ ! 11472: EQPGraphRow *pRow, *pNext; ! 11473: int n = strlen30(p->sGraph.zPrefix); ! 11474: char *z; ! 11475: for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ ! 11476: pNext = eqp_next_row(p, iEqpId, pRow); ! 11477: z = pRow->zText; ! 11478: utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, ! 11479: pNext ? "|--" : "`--", z); ! 11480: if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ ! 11481: memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); ! 11482: eqp_render_level(p, pRow->iEqpId); ! 11483: p->sGraph.zPrefix[n] = 0; ! 11484: } ! 11485: } ! 11486: } ! 11487: ! 11488: /* ! 11489: ** Display and reset the EXPLAIN QUERY PLAN data ! 11490: */ ! 11491: static void eqp_render(ShellState *p){ ! 11492: EQPGraphRow *pRow = p->sGraph.pRow; ! 11493: if( pRow ){ ! 11494: if( pRow->zText[0]=='-' ){ ! 11495: if( pRow->pNext==0 ){ ! 11496: eqp_reset(p); ! 11497: return; ! 11498: } ! 11499: utf8_printf(p->out, "%s\n", pRow->zText+3); ! 11500: p->sGraph.pRow = pRow->pNext; ! 11501: sqlite3_free(pRow); ! 11502: }else{ ! 11503: utf8_printf(p->out, "QUERY PLAN\n"); ! 11504: } ! 11505: p->sGraph.zPrefix[0] = 0; ! 11506: eqp_render_level(p, 0); ! 11507: eqp_reset(p); ! 11508: } ! 11509: } ! 11510: ! 11511: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK ! 11512: /* ! 11513: ** Progress handler callback. ! 11514: */ ! 11515: static int progress_handler(void *pClientData) { ! 11516: ShellState *p = (ShellState*)pClientData; ! 11517: p->nProgress++; ! 11518: if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ ! 11519: raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); ! 11520: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; ! 11521: if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; ! 11522: return 1; ! 11523: } ! 11524: if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){ ! 11525: raw_printf(p->out, "Progress %u\n", p->nProgress); ! 11526: } ! 11527: return 0; ! 11528: } ! 11529: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ ! 11530: ! 11531: /* ! 11532: ** Print N dashes ! 11533: */ ! 11534: static void print_dashes(FILE *out, int N){ ! 11535: const char zDash[] = "--------------------------------------------------"; ! 11536: const int nDash = sizeof(zDash) - 1; ! 11537: while( N>nDash ){ ! 11538: fputs(zDash, out); ! 11539: N -= nDash; ! 11540: } ! 11541: raw_printf(out, "%.*s", N, zDash); ! 11542: } ! 11543: ! 11544: /* ! 11545: ** Print a markdown or table-style row separator using ascii-art ! 11546: */ ! 11547: static void print_row_separator( ! 11548: ShellState *p, ! 11549: int nArg, ! 11550: const char *zSep ! 11551: ){ ! 11552: int i; ! 11553: if( nArg>0 ){ ! 11554: fputs(zSep, p->out); ! 11555: print_dashes(p->out, p->actualWidth[0]+2); ! 11556: for(i=1; i<nArg; i++){ ! 11557: fputs(zSep, p->out); ! 11558: print_dashes(p->out, p->actualWidth[i]+2); ! 11559: } ! 11560: fputs(zSep, p->out); ! 11561: } ! 11562: fputs("\n", p->out); ! 11563: } ! 11564: ! 11565: /* ! 11566: ** This is the callback routine that the shell ! 11567: ** invokes for each row of a query result. ! 11568: */ ! 11569: static int shell_callback( ! 11570: void *pArg, ! 11571: int nArg, /* Number of result columns */ ! 11572: char **azArg, /* Text of each result column */ ! 11573: char **azCol, /* Column names */ ! 11574: int *aiType /* Column types. Might be NULL */ ! 11575: ){ ! 11576: int i; ! 11577: ShellState *p = (ShellState*)pArg; ! 11578: ! 11579: if( azArg==0 ) return 0; ! 11580: switch( p->cMode ){ ! 11581: case MODE_Line: { ! 11582: int w = 5; ! 11583: if( azArg==0 ) break; ! 11584: for(i=0; i<nArg; i++){ ! 11585: int len = strlen30(azCol[i] ? azCol[i] : ""); ! 11586: if( len>w ) w = len; ! 11587: } ! 11588: if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); ! 11589: for(i=0; i<nArg; i++){ ! 11590: utf8_printf(p->out,"%*s = %s%s", w, azCol[i], ! 11591: azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); ! 11592: } ! 11593: break; ! 11594: } ! 11595: case MODE_Explain: { ! 11596: static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13}; ! 11597: if( nArg>ArraySize(aExplainWidth) ){ ! 11598: nArg = ArraySize(aExplainWidth); ! 11599: } ! 11600: if( p->cnt++==0 ){ ! 11601: for(i=0; i<nArg; i++){ ! 11602: int w = aExplainWidth[i]; ! 11603: utf8_width_print(p->out, w, azCol[i]); ! 11604: fputs(i==nArg-1 ? "\n" : " ", p->out); ! 11605: } ! 11606: for(i=0; i<nArg; i++){ ! 11607: int w = aExplainWidth[i]; ! 11608: print_dashes(p->out, w); ! 11609: fputs(i==nArg-1 ? "\n" : " ", p->out); ! 11610: } ! 11611: } ! 11612: if( azArg==0 ) break; ! 11613: for(i=0; i<nArg; i++){ ! 11614: int w = aExplainWidth[i]; ! 11615: if( azArg[i] && strlenChar(azArg[i])>w ){ ! 11616: w = strlenChar(azArg[i]); ! 11617: } ! 11618: if( i==1 && p->aiIndent && p->pStmt ){ ! 11619: if( p->iIndent<p->nIndent ){ ! 11620: utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); ! 11621: } ! 11622: p->iIndent++; ! 11623: } ! 11624: utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue); ! 11625: fputs(i==nArg-1 ? "\n" : " ", p->out); ! 11626: } ! 11627: break; ! 11628: } ! 11629: case MODE_Semi: { /* .schema and .fullschema output */ ! 11630: printSchemaLine(p->out, azArg[0], ";\n"); ! 11631: break; ! 11632: } ! 11633: case MODE_Pretty: { /* .schema and .fullschema with --indent */ ! 11634: char *z; ! 11635: int j; ! 11636: int nParen = 0; ! 11637: char cEnd = 0; ! 11638: char c; ! 11639: int nLine = 0; ! 11640: assert( nArg==1 ); ! 11641: if( azArg[0]==0 ) break; ! 11642: if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 ! 11643: || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 ! 11644: ){ ! 11645: utf8_printf(p->out, "%s;\n", azArg[0]); ! 11646: break; ! 11647: } ! 11648: z = sqlite3_mprintf("%s", azArg[0]); ! 11649: j = 0; ! 11650: for(i=0; IsSpace(z[i]); i++){} ! 11651: for(; (c = z[i])!=0; i++){ ! 11652: if( IsSpace(c) ){ ! 11653: if( z[j-1]=='\r' ) z[j-1] = '\n'; ! 11654: if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; ! 11655: }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ ! 11656: j--; ! 11657: } ! 11658: z[j++] = c; ! 11659: } ! 11660: while( j>0 && IsSpace(z[j-1]) ){ j--; } ! 11661: z[j] = 0; ! 11662: if( strlen30(z)>=79 ){ ! 11663: for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ ! 11664: if( c==cEnd ){ ! 11665: cEnd = 0; ! 11666: }else if( c=='"' || c=='\'' || c=='`' ){ ! 11667: cEnd = c; ! 11668: }else if( c=='[' ){ ! 11669: cEnd = ']'; ! 11670: }else if( c=='-' && z[i+1]=='-' ){ ! 11671: cEnd = '\n'; ! 11672: }else if( c=='(' ){ ! 11673: nParen++; ! 11674: }else if( c==')' ){ ! 11675: nParen--; ! 11676: if( nLine>0 && nParen==0 && j>0 ){ ! 11677: printSchemaLineN(p->out, z, j, "\n"); ! 11678: j = 0; ! 11679: } ! 11680: } ! 11681: z[j++] = c; ! 11682: if( nParen==1 && cEnd==0 ! 11683: && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) ! 11684: ){ ! 11685: if( c=='\n' ) j--; ! 11686: printSchemaLineN(p->out, z, j, "\n "); ! 11687: j = 0; ! 11688: nLine++; ! 11689: while( IsSpace(z[i+1]) ){ i++; } ! 11690: } ! 11691: } ! 11692: z[j] = 0; ! 11693: } ! 11694: printSchemaLine(p->out, z, ";\n"); ! 11695: sqlite3_free(z); ! 11696: break; ! 11697: } ! 11698: case MODE_List: { ! 11699: if( p->cnt++==0 && p->showHeader ){ ! 11700: for(i=0; i<nArg; i++){ ! 11701: utf8_printf(p->out,"%s%s",azCol[i], ! 11702: i==nArg-1 ? p->rowSeparator : p->colSeparator); ! 11703: } ! 11704: } ! 11705: if( azArg==0 ) break; ! 11706: for(i=0; i<nArg; i++){ ! 11707: char *z = azArg[i]; ! 11708: if( z==0 ) z = p->nullValue; ! 11709: utf8_printf(p->out, "%s", z); ! 11710: if( i<nArg-1 ){ ! 11711: utf8_printf(p->out, "%s", p->colSeparator); ! 11712: }else{ ! 11713: utf8_printf(p->out, "%s", p->rowSeparator); ! 11714: } ! 11715: } ! 11716: break; ! 11717: } ! 11718: case MODE_Html: { ! 11719: if( p->cnt++==0 && p->showHeader ){ ! 11720: raw_printf(p->out,"<TR>"); ! 11721: for(i=0; i<nArg; i++){ ! 11722: raw_printf(p->out,"<TH>"); ! 11723: output_html_string(p->out, azCol[i]); ! 11724: raw_printf(p->out,"</TH>\n"); ! 11725: } ! 11726: raw_printf(p->out,"</TR>\n"); ! 11727: } ! 11728: if( azArg==0 ) break; ! 11729: raw_printf(p->out,"<TR>"); ! 11730: for(i=0; i<nArg; i++){ ! 11731: raw_printf(p->out,"<TD>"); ! 11732: output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); ! 11733: raw_printf(p->out,"</TD>\n"); ! 11734: } ! 11735: raw_printf(p->out,"</TR>\n"); ! 11736: break; ! 11737: } ! 11738: case MODE_Tcl: { ! 11739: if( p->cnt++==0 && p->showHeader ){ ! 11740: for(i=0; i<nArg; i++){ ! 11741: output_c_string(p->out,azCol[i] ? azCol[i] : ""); ! 11742: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator); ! 11743: } ! 11744: utf8_printf(p->out, "%s", p->rowSeparator); ! 11745: } ! 11746: if( azArg==0 ) break; ! 11747: for(i=0; i<nArg; i++){ ! 11748: output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue); ! 11749: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator); ! 11750: } ! 11751: utf8_printf(p->out, "%s", p->rowSeparator); ! 11752: break; ! 11753: } ! 11754: case MODE_Csv: { ! 11755: setBinaryMode(p->out, 1); ! 11756: if( p->cnt++==0 && p->showHeader ){ ! 11757: for(i=0; i<nArg; i++){ ! 11758: output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); ! 11759: } ! 11760: utf8_printf(p->out, "%s", p->rowSeparator); ! 11761: } ! 11762: if( nArg>0 ){ ! 11763: for(i=0; i<nArg; i++){ ! 11764: output_csv(p, azArg[i], i<nArg-1); ! 11765: } ! 11766: utf8_printf(p->out, "%s", p->rowSeparator); ! 11767: } ! 11768: setTextMode(p->out, 1); ! 11769: break; ! 11770: } ! 11771: case MODE_Insert: { ! 11772: if( azArg==0 ) break; ! 11773: utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); ! 11774: if( p->showHeader ){ ! 11775: raw_printf(p->out,"("); ! 11776: for(i=0; i<nArg; i++){ ! 11777: if( i>0 ) raw_printf(p->out, ","); ! 11778: if( quoteChar(azCol[i]) ){ ! 11779: char *z = sqlite3_mprintf("\"%w\"", azCol[i]); ! 11780: utf8_printf(p->out, "%s", z); ! 11781: sqlite3_free(z); ! 11782: }else{ ! 11783: raw_printf(p->out, "%s", azCol[i]); ! 11784: } ! 11785: } ! 11786: raw_printf(p->out,")"); ! 11787: } ! 11788: p->cnt++; ! 11789: for(i=0; i<nArg; i++){ ! 11790: raw_printf(p->out, i>0 ? "," : " VALUES("); ! 11791: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ ! 11792: utf8_printf(p->out,"NULL"); ! 11793: }else if( aiType && aiType[i]==SQLITE_TEXT ){ ! 11794: if( ShellHasFlag(p, SHFLG_Newlines) ){ ! 11795: output_quoted_string(p->out, azArg[i]); ! 11796: }else{ ! 11797: output_quoted_escaped_string(p->out, azArg[i]); ! 11798: } ! 11799: }else if( aiType && aiType[i]==SQLITE_INTEGER ){ ! 11800: utf8_printf(p->out,"%s", azArg[i]); ! 11801: }else if( aiType && aiType[i]==SQLITE_FLOAT ){ ! 11802: char z[50]; ! 11803: double r = sqlite3_column_double(p->pStmt, i); ! 11804: sqlite3_uint64 ur; ! 11805: memcpy(&ur,&r,sizeof(r)); ! 11806: if( ur==0x7ff0000000000000LL ){ ! 11807: raw_printf(p->out, "1e999"); ! 11808: }else if( ur==0xfff0000000000000LL ){ ! 11809: raw_printf(p->out, "-1e999"); ! 11810: }else{ ! 11811: sqlite3_snprintf(50,z,"%!.20g", r); ! 11812: raw_printf(p->out, "%s", z); ! 11813: } ! 11814: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ ! 11815: const void *pBlob = sqlite3_column_blob(p->pStmt, i); ! 11816: int nBlob = sqlite3_column_bytes(p->pStmt, i); ! 11817: output_hex_blob(p->out, pBlob, nBlob); ! 11818: }else if( isNumber(azArg[i], 0) ){ ! 11819: utf8_printf(p->out,"%s", azArg[i]); ! 11820: }else if( ShellHasFlag(p, SHFLG_Newlines) ){ ! 11821: output_quoted_string(p->out, azArg[i]); ! 11822: }else{ ! 11823: output_quoted_escaped_string(p->out, azArg[i]); ! 11824: } ! 11825: } ! 11826: raw_printf(p->out,");\n"); ! 11827: break; ! 11828: } ! 11829: case MODE_Json: { ! 11830: if( azArg==0 ) break; ! 11831: if( p->cnt==0 ){ ! 11832: fputs("[{", p->out); ! 11833: }else{ ! 11834: fputs(",\n{", p->out); ! 11835: } ! 11836: p->cnt++; ! 11837: for(i=0; i<nArg; i++){ ! 11838: output_json_string(p->out, azCol[i], -1); ! 11839: putc(':', p->out); ! 11840: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ ! 11841: fputs("null",p->out); ! 11842: }else if( aiType && aiType[i]==SQLITE_FLOAT ){ ! 11843: char z[50]; ! 11844: double r = sqlite3_column_double(p->pStmt, i); ! 11845: sqlite3_uint64 ur; ! 11846: memcpy(&ur,&r,sizeof(r)); ! 11847: if( ur==0x7ff0000000000000LL ){ ! 11848: raw_printf(p->out, "1e999"); ! 11849: }else if( ur==0xfff0000000000000LL ){ ! 11850: raw_printf(p->out, "-1e999"); ! 11851: }else{ ! 11852: sqlite3_snprintf(50,z,"%!.20g", r); ! 11853: raw_printf(p->out, "%s", z); ! 11854: } ! 11855: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ ! 11856: const void *pBlob = sqlite3_column_blob(p->pStmt, i); ! 11857: int nBlob = sqlite3_column_bytes(p->pStmt, i); ! 11858: output_json_string(p->out, pBlob, nBlob); ! 11859: }else if( aiType && aiType[i]==SQLITE_TEXT ){ ! 11860: output_json_string(p->out, azArg[i], -1); ! 11861: }else{ ! 11862: utf8_printf(p->out,"%s", azArg[i]); ! 11863: } ! 11864: if( i<nArg-1 ){ ! 11865: putc(',', p->out); ! 11866: } ! 11867: } ! 11868: putc('}', p->out); ! 11869: break; ! 11870: } ! 11871: case MODE_Quote: { ! 11872: if( azArg==0 ) break; ! 11873: if( p->cnt==0 && p->showHeader ){ ! 11874: for(i=0; i<nArg; i++){ ! 11875: if( i>0 ) fputs(p->colSeparator, p->out); ! 11876: output_quoted_string(p->out, azCol[i]); ! 11877: } ! 11878: fputs(p->rowSeparator, p->out); ! 11879: } ! 11880: p->cnt++; ! 11881: for(i=0; i<nArg; i++){ ! 11882: if( i>0 ) fputs(p->colSeparator, p->out); ! 11883: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ ! 11884: utf8_printf(p->out,"NULL"); ! 11885: }else if( aiType && aiType[i]==SQLITE_TEXT ){ ! 11886: output_quoted_string(p->out, azArg[i]); ! 11887: }else if( aiType && aiType[i]==SQLITE_INTEGER ){ ! 11888: utf8_printf(p->out,"%s", azArg[i]); ! 11889: }else if( aiType && aiType[i]==SQLITE_FLOAT ){ ! 11890: char z[50]; ! 11891: double r = sqlite3_column_double(p->pStmt, i); ! 11892: sqlite3_snprintf(50,z,"%!.20g", r); ! 11893: raw_printf(p->out, "%s", z); ! 11894: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ ! 11895: const void *pBlob = sqlite3_column_blob(p->pStmt, i); ! 11896: int nBlob = sqlite3_column_bytes(p->pStmt, i); ! 11897: output_hex_blob(p->out, pBlob, nBlob); ! 11898: }else if( isNumber(azArg[i], 0) ){ ! 11899: utf8_printf(p->out,"%s", azArg[i]); ! 11900: }else{ ! 11901: output_quoted_string(p->out, azArg[i]); ! 11902: } ! 11903: } ! 11904: fputs(p->rowSeparator, p->out); ! 11905: break; ! 11906: } ! 11907: case MODE_Ascii: { ! 11908: if( p->cnt++==0 && p->showHeader ){ ! 11909: for(i=0; i<nArg; i++){ ! 11910: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); ! 11911: utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); ! 11912: } ! 11913: utf8_printf(p->out, "%s", p->rowSeparator); ! 11914: } ! 11915: if( azArg==0 ) break; ! 11916: for(i=0; i<nArg; i++){ ! 11917: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); ! 11918: utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); ! 11919: } ! 11920: utf8_printf(p->out, "%s", p->rowSeparator); ! 11921: break; ! 11922: } ! 11923: case MODE_EQP: { ! 11924: eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); ! 11925: break; ! 11926: } ! 11927: } ! 11928: return 0; ! 11929: } ! 11930: ! 11931: /* ! 11932: ** This is the callback routine that the SQLite library ! 11933: ** invokes for each row of a query result. ! 11934: */ ! 11935: static int callback(void *pArg, int nArg, char **azArg, char **azCol){ ! 11936: /* since we don't have type info, call the shell_callback with a NULL value */ ! 11937: return shell_callback(pArg, nArg, azArg, azCol, NULL); ! 11938: } ! 11939: ! 11940: /* ! 11941: ** This is the callback routine from sqlite3_exec() that appends all ! 11942: ** output onto the end of a ShellText object. ! 11943: */ ! 11944: static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ ! 11945: ShellText *p = (ShellText*)pArg; ! 11946: int i; ! 11947: UNUSED_PARAMETER(az); ! 11948: if( azArg==0 ) return 0; ! 11949: if( p->n ) appendText(p, "|", 0); ! 11950: for(i=0; i<nArg; i++){ ! 11951: if( i ) appendText(p, ",", 0); ! 11952: if( azArg[i] ) appendText(p, azArg[i], 0); ! 11953: } ! 11954: return 0; ! 11955: } ! 11956: ! 11957: /* ! 11958: ** Generate an appropriate SELFTEST table in the main database. ! 11959: */ ! 11960: static void createSelftestTable(ShellState *p){ ! 11961: char *zErrMsg = 0; ! 11962: sqlite3_exec(p->db, ! 11963: "SAVEPOINT selftest_init;\n" ! 11964: "CREATE TABLE IF NOT EXISTS selftest(\n" ! 11965: " tno INTEGER PRIMARY KEY,\n" /* Test number */ ! 11966: " op TEXT,\n" /* Operator: memo run */ ! 11967: " cmd TEXT,\n" /* Command text */ ! 11968: " ans TEXT\n" /* Desired answer */ ! 11969: ");" ! 11970: "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" ! 11971: "INSERT INTO [_shell$self](rowid,op,cmd)\n" ! 11972: " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" ! 11973: " 'memo','Tests generated by --init');\n" ! 11974: "INSERT INTO [_shell$self]\n" ! 11975: " SELECT 'run',\n" ! 11976: " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " ! 11977: "FROM sqlite_schema ORDER BY 2'',224))',\n" ! 11978: " hex(sha3_query('SELECT type,name,tbl_name,sql " ! 11979: "FROM sqlite_schema ORDER BY 2',224));\n" ! 11980: "INSERT INTO [_shell$self]\n" ! 11981: " SELECT 'run'," ! 11982: " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" ! 11983: " printf('%w',name) || '\" NOT INDEXED'',224))',\n" ! 11984: " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" ! 11985: " FROM (\n" ! 11986: " SELECT name FROM sqlite_schema\n" ! 11987: " WHERE type='table'\n" ! 11988: " AND name<>'selftest'\n" ! 11989: " AND coalesce(rootpage,0)>0\n" ! 11990: " )\n" ! 11991: " ORDER BY name;\n" ! 11992: "INSERT INTO [_shell$self]\n" ! 11993: " VALUES('run','PRAGMA integrity_check','ok');\n" ! 11994: "INSERT INTO selftest(tno,op,cmd,ans)" ! 11995: " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" ! 11996: "DROP TABLE [_shell$self];" ! 11997: ,0,0,&zErrMsg); ! 11998: if( zErrMsg ){ ! 11999: utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); ! 12000: sqlite3_free(zErrMsg); ! 12001: } ! 12002: sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); ! 12003: } ! 12004: ! 12005: ! 12006: /* ! 12007: ** Set the destination table field of the ShellState structure to ! 12008: ** the name of the table given. Escape any quote characters in the ! 12009: ** table name. ! 12010: */ ! 12011: static void set_table_name(ShellState *p, const char *zName){ ! 12012: int i, n; ! 12013: char cQuote; ! 12014: char *z; ! 12015: ! 12016: if( p->zDestTable ){ ! 12017: free(p->zDestTable); ! 12018: p->zDestTable = 0; ! 12019: } ! 12020: if( zName==0 ) return; ! 12021: cQuote = quoteChar(zName); ! 12022: n = strlen30(zName); ! 12023: if( cQuote ) n += n+2; ! 12024: z = p->zDestTable = malloc( n+1 ); ! 12025: if( z==0 ) shell_out_of_memory(); ! 12026: n = 0; ! 12027: if( cQuote ) z[n++] = cQuote; ! 12028: for(i=0; zName[i]; i++){ ! 12029: z[n++] = zName[i]; ! 12030: if( zName[i]==cQuote ) z[n++] = cQuote; ! 12031: } ! 12032: if( cQuote ) z[n++] = cQuote; ! 12033: z[n] = 0; ! 12034: } ! 12035: ! 12036: ! 12037: /* ! 12038: ** Execute a query statement that will generate SQL output. Print ! 12039: ** the result columns, comma-separated, on a line and then add a ! 12040: ** semicolon terminator to the end of that line. ! 12041: ** ! 12042: ** If the number of columns is 1 and that column contains text "--" ! 12043: ** then write the semicolon on a separate line. That way, if a ! 12044: ** "--" comment occurs at the end of the statement, the comment ! 12045: ** won't consume the semicolon terminator. ! 12046: */ ! 12047: static int run_table_dump_query( ! 12048: ShellState *p, /* Query context */ ! 12049: const char *zSelect /* SELECT statement to extract content */ ! 12050: ){ ! 12051: sqlite3_stmt *pSelect; ! 12052: int rc; ! 12053: int nResult; ! 12054: int i; ! 12055: const char *z; ! 12056: rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); ! 12057: if( rc!=SQLITE_OK || !pSelect ){ ! 12058: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, ! 12059: sqlite3_errmsg(p->db)); ! 12060: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; ! 12061: return rc; ! 12062: } ! 12063: rc = sqlite3_step(pSelect); ! 12064: nResult = sqlite3_column_count(pSelect); ! 12065: while( rc==SQLITE_ROW ){ ! 12066: z = (const char*)sqlite3_column_text(pSelect, 0); ! 12067: utf8_printf(p->out, "%s", z); ! 12068: for(i=1; i<nResult; i++){ ! 12069: utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i)); ! 12070: } ! 12071: if( z==0 ) z = ""; ! 12072: while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; ! 12073: if( z[0] ){ ! 12074: raw_printf(p->out, "\n;\n"); ! 12075: }else{ ! 12076: raw_printf(p->out, ";\n"); ! 12077: } ! 12078: rc = sqlite3_step(pSelect); ! 12079: } ! 12080: rc = sqlite3_finalize(pSelect); ! 12081: if( rc!=SQLITE_OK ){ ! 12082: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, ! 12083: sqlite3_errmsg(p->db)); ! 12084: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; ! 12085: } ! 12086: return rc; ! 12087: } ! 12088: ! 12089: /* ! 12090: ** Allocate space and save off current error string. ! 12091: */ ! 12092: static char *save_err_msg( ! 12093: sqlite3 *db /* Database to query */ ! 12094: ){ ! 12095: int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); ! 12096: char *zErrMsg = sqlite3_malloc64(nErrMsg); ! 12097: if( zErrMsg ){ ! 12098: memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); ! 12099: } ! 12100: return zErrMsg; ! 12101: } ! 12102: ! 12103: #ifdef __linux__ ! 12104: /* ! 12105: ** Attempt to display I/O stats on Linux using /proc/PID/io ! 12106: */ ! 12107: static void displayLinuxIoStats(FILE *out){ ! 12108: FILE *in; ! 12109: char z[200]; ! 12110: sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); ! 12111: in = fopen(z, "rb"); ! 12112: if( in==0 ) return; ! 12113: while( fgets(z, sizeof(z), in)!=0 ){ ! 12114: static const struct { ! 12115: const char *zPattern; ! 12116: const char *zDesc; ! 12117: } aTrans[] = { ! 12118: { "rchar: ", "Bytes received by read():" }, ! 12119: { "wchar: ", "Bytes sent to write():" }, ! 12120: { "syscr: ", "Read() system calls:" }, ! 12121: { "syscw: ", "Write() system calls:" }, ! 12122: { "read_bytes: ", "Bytes read from storage:" }, ! 12123: { "write_bytes: ", "Bytes written to storage:" }, ! 12124: { "cancelled_write_bytes: ", "Cancelled write bytes:" }, ! 12125: }; ! 12126: int i; ! 12127: for(i=0; i<ArraySize(aTrans); i++){ ! 12128: int n = strlen30(aTrans[i].zPattern); ! 12129: if( strncmp(aTrans[i].zPattern, z, n)==0 ){ ! 12130: utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]); ! 12131: break; ! 12132: } ! 12133: } ! 12134: } ! 12135: fclose(in); ! 12136: } ! 12137: #endif ! 12138: ! 12139: /* ! 12140: ** Display a single line of status using 64-bit values. ! 12141: */ ! 12142: static void displayStatLine( ! 12143: ShellState *p, /* The shell context */ ! 12144: char *zLabel, /* Label for this one line */ ! 12145: char *zFormat, /* Format for the result */ ! 12146: int iStatusCtrl, /* Which status to display */ ! 12147: int bReset /* True to reset the stats */ ! 12148: ){ ! 12149: sqlite3_int64 iCur = -1; ! 12150: sqlite3_int64 iHiwtr = -1; ! 12151: int i, nPercent; ! 12152: char zLine[200]; ! 12153: sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset); ! 12154: for(i=0, nPercent=0; zFormat[i]; i++){ ! 12155: if( zFormat[i]=='%' ) nPercent++; ! 12156: } ! 12157: if( nPercent>1 ){ ! 12158: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); ! 12159: }else{ ! 12160: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); ! 12161: } ! 12162: raw_printf(p->out, "%-36s %s\n", zLabel, zLine); ! 12163: } ! 12164: ! 12165: /* ! 12166: ** Display memory stats. ! 12167: */ ! 12168: static int display_stats( ! 12169: sqlite3 *db, /* Database to query */ ! 12170: ShellState *pArg, /* Pointer to ShellState */ ! 12171: int bReset /* True to reset the stats */ ! 12172: ){ ! 12173: int iCur; ! 12174: int iHiwtr; ! 12175: FILE *out; ! 12176: if( pArg==0 || pArg->out==0 ) return 0; ! 12177: out = pArg->out; ! 12178: ! 12179: if( pArg->pStmt && (pArg->statsOn & 2) ){ ! 12180: int nCol, i, x; ! 12181: sqlite3_stmt *pStmt = pArg->pStmt; ! 12182: char z[100]; ! 12183: nCol = sqlite3_column_count(pStmt); ! 12184: raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol); ! 12185: for(i=0; i<nCol; i++){ ! 12186: sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x); ! 12187: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i)); ! 12188: #ifndef SQLITE_OMIT_DECLTYPE ! 12189: sqlite3_snprintf(30, z+x, "declared type:"); ! 12190: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i)); ! 12191: #endif ! 12192: #ifdef SQLITE_ENABLE_COLUMN_METADATA ! 12193: sqlite3_snprintf(30, z+x, "database name:"); ! 12194: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i)); ! 12195: sqlite3_snprintf(30, z+x, "table name:"); ! 12196: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i)); ! 12197: sqlite3_snprintf(30, z+x, "origin name:"); ! 12198: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i)); ! 12199: #endif ! 12200: } ! 12201: } ! 12202: ! 12203: displayStatLine(pArg, "Memory Used:", ! 12204: "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); ! 12205: displayStatLine(pArg, "Number of Outstanding Allocations:", ! 12206: "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); ! 12207: if( pArg->shellFlgs & SHFLG_Pagecache ){ ! 12208: displayStatLine(pArg, "Number of Pcache Pages Used:", ! 12209: "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); ! 12210: } ! 12211: displayStatLine(pArg, "Number of Pcache Overflow Bytes:", ! 12212: "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); ! 12213: displayStatLine(pArg, "Largest Allocation:", ! 12214: "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); ! 12215: displayStatLine(pArg, "Largest Pcache Allocation:", ! 12216: "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); ! 12217: #ifdef YYTRACKMAXSTACKDEPTH ! 12218: displayStatLine(pArg, "Deepest Parser Stack:", ! 12219: "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); ! 12220: #endif ! 12221: ! 12222: if( db ){ ! 12223: if( pArg->shellFlgs & SHFLG_Lookaside ){ ! 12224: iHiwtr = iCur = -1; ! 12225: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, ! 12226: &iCur, &iHiwtr, bReset); ! 12227: raw_printf(pArg->out, ! 12228: "Lookaside Slots Used: %d (max %d)\n", ! 12229: iCur, iHiwtr); ! 12230: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, ! 12231: &iCur, &iHiwtr, bReset); ! 12232: raw_printf(pArg->out, "Successful lookaside attempts: %d\n", ! 12233: iHiwtr); ! 12234: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, ! 12235: &iCur, &iHiwtr, bReset); ! 12236: raw_printf(pArg->out, "Lookaside failures due to size: %d\n", ! 12237: iHiwtr); ! 12238: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, ! 12239: &iCur, &iHiwtr, bReset); ! 12240: raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n", ! 12241: iHiwtr); ! 12242: } ! 12243: iHiwtr = iCur = -1; ! 12244: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); ! 12245: raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", ! 12246: iCur); ! 12247: iHiwtr = iCur = -1; ! 12248: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); ! 12249: raw_printf(pArg->out, "Page cache hits: %d\n", iCur); ! 12250: iHiwtr = iCur = -1; ! 12251: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); ! 12252: raw_printf(pArg->out, "Page cache misses: %d\n", iCur); ! 12253: iHiwtr = iCur = -1; ! 12254: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); ! 12255: raw_printf(pArg->out, "Page cache writes: %d\n", iCur); ! 12256: iHiwtr = iCur = -1; ! 12257: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); ! 12258: raw_printf(pArg->out, "Page cache spills: %d\n", iCur); ! 12259: iHiwtr = iCur = -1; ! 12260: sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); ! 12261: raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", ! 12262: iCur); ! 12263: iHiwtr = iCur = -1; ! 12264: sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); ! 12265: raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", ! 12266: iCur); ! 12267: } ! 12268: ! 12269: if( pArg->pStmt ){ ! 12270: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, ! 12271: bReset); ! 12272: raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); ! 12273: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); ! 12274: raw_printf(pArg->out, "Sort Operations: %d\n", iCur); ! 12275: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); ! 12276: raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); ! 12277: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); ! 12278: raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); ! 12279: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); ! 12280: raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); ! 12281: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); ! 12282: raw_printf(pArg->out, "Number of times run: %d\n", iCur); ! 12283: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); ! 12284: raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur); ! 12285: } ! 12286: ! 12287: #ifdef __linux__ ! 12288: displayLinuxIoStats(pArg->out); ! 12289: #endif ! 12290: ! 12291: /* Do not remove this machine readable comment: extra-stats-output-here */ ! 12292: ! 12293: return 0; ! 12294: } ! 12295: ! 12296: /* ! 12297: ** Display scan stats. ! 12298: */ ! 12299: static void display_scanstats( ! 12300: sqlite3 *db, /* Database to query */ ! 12301: ShellState *pArg /* Pointer to ShellState */ ! 12302: ){ ! 12303: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS ! 12304: UNUSED_PARAMETER(db); ! 12305: UNUSED_PARAMETER(pArg); ! 12306: #else ! 12307: int i, k, n, mx; ! 12308: raw_printf(pArg->out, "-------- scanstats --------\n"); ! 12309: mx = 0; ! 12310: for(k=0; k<=mx; k++){ ! 12311: double rEstLoop = 1.0; ! 12312: for(i=n=0; 1; i++){ ! 12313: sqlite3_stmt *p = pArg->pStmt; ! 12314: sqlite3_int64 nLoop, nVisit; ! 12315: double rEst; ! 12316: int iSid; ! 12317: const char *zExplain; ! 12318: if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){ ! 12319: break; ! 12320: } ! 12321: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid); ! 12322: if( iSid>mx ) mx = iSid; ! 12323: if( iSid!=k ) continue; ! 12324: if( n==0 ){ ! 12325: rEstLoop = (double)nLoop; ! 12326: if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k); ! 12327: } ! 12328: n++; ! 12329: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); ! 12330: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); ! 12331: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); ! 12332: utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); ! 12333: rEstLoop *= rEst; ! 12334: raw_printf(pArg->out, ! 12335: " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", ! 12336: nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst ! 12337: ); ! 12338: } ! 12339: } ! 12340: raw_printf(pArg->out, "---------------------------\n"); ! 12341: #endif ! 12342: } ! 12343: ! 12344: /* ! 12345: ** Parameter azArray points to a zero-terminated array of strings. zStr ! 12346: ** points to a single nul-terminated string. Return non-zero if zStr ! 12347: ** is equal, according to strcmp(), to any of the strings in the array. ! 12348: ** Otherwise, return zero. ! 12349: */ ! 12350: static int str_in_array(const char *zStr, const char **azArray){ ! 12351: int i; ! 12352: for(i=0; azArray[i]; i++){ ! 12353: if( 0==strcmp(zStr, azArray[i]) ) return 1; ! 12354: } ! 12355: return 0; ! 12356: } ! 12357: ! 12358: /* ! 12359: ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ! 12360: ** and populate the ShellState.aiIndent[] array with the number of ! 12361: ** spaces each opcode should be indented before it is output. ! 12362: ** ! 12363: ** The indenting rules are: ! 12364: ** ! 12365: ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent ! 12366: ** all opcodes that occur between the p2 jump destination and the opcode ! 12367: ** itself by 2 spaces. ! 12368: ** ! 12369: ** * For each "Goto", if the jump destination is earlier in the program ! 12370: ** and ends on one of: ! 12371: ** Yield SeekGt SeekLt RowSetRead Rewind ! 12372: ** or if the P1 parameter is one instead of zero, ! 12373: ** then indent all opcodes between the earlier instruction ! 12374: ** and "Goto" by 2 spaces. ! 12375: */ ! 12376: static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ ! 12377: const char *zSql; /* The text of the SQL statement */ ! 12378: const char *z; /* Used to check if this is an EXPLAIN */ ! 12379: int *abYield = 0; /* True if op is an OP_Yield */ ! 12380: int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ ! 12381: int iOp; /* Index of operation in p->aiIndent[] */ ! 12382: ! 12383: const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; ! 12384: const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", ! 12385: "Rewind", 0 }; ! 12386: const char *azGoto[] = { "Goto", 0 }; ! 12387: ! 12388: /* Try to figure out if this is really an EXPLAIN statement. If this ! 12389: ** cannot be verified, return early. */ ! 12390: if( sqlite3_column_count(pSql)!=8 ){ ! 12391: p->cMode = p->mode; ! 12392: return; ! 12393: } ! 12394: zSql = sqlite3_sql(pSql); ! 12395: if( zSql==0 ) return; ! 12396: for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); ! 12397: if( sqlite3_strnicmp(z, "explain", 7) ){ ! 12398: p->cMode = p->mode; ! 12399: return; ! 12400: } ! 12401: ! 12402: for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ ! 12403: int i; ! 12404: int iAddr = sqlite3_column_int(pSql, 0); ! 12405: const char *zOp = (const char*)sqlite3_column_text(pSql, 1); ! 12406: ! 12407: /* Set p2 to the P2 field of the current opcode. Then, assuming that ! 12408: ** p2 is an instruction address, set variable p2op to the index of that ! 12409: ** instruction in the aiIndent[] array. p2 and p2op may be different if ! 12410: ** the current instruction is part of a sub-program generated by an ! 12411: ** SQL trigger or foreign key. */ ! 12412: int p2 = sqlite3_column_int(pSql, 3); ! 12413: int p2op = (p2 + (iOp-iAddr)); ! 12414: ! 12415: /* Grow the p->aiIndent array as required */ ! 12416: if( iOp>=nAlloc ){ ! 12417: if( iOp==0 ){ ! 12418: /* Do further verfication that this is explain output. Abort if ! 12419: ** it is not */ ! 12420: static const char *explainCols[] = { ! 12421: "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; ! 12422: int jj; ! 12423: for(jj=0; jj<ArraySize(explainCols); jj++){ ! 12424: if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){ ! 12425: p->cMode = p->mode; ! 12426: sqlite3_reset(pSql); ! 12427: return; ! 12428: } ! 12429: } ! 12430: } ! 12431: nAlloc += 100; ! 12432: p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); ! 12433: if( p->aiIndent==0 ) shell_out_of_memory(); ! 12434: abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); ! 12435: if( abYield==0 ) shell_out_of_memory(); ! 12436: } ! 12437: abYield[iOp] = str_in_array(zOp, azYield); ! 12438: p->aiIndent[iOp] = 0; ! 12439: p->nIndent = iOp+1; ! 12440: ! 12441: if( str_in_array(zOp, azNext) ){ ! 12442: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; ! 12443: } ! 12444: if( str_in_array(zOp, azGoto) && p2op<p->nIndent ! 12445: && (abYield[p2op] || sqlite3_column_int(pSql, 2)) ! 12446: ){ ! 12447: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; ! 12448: } ! 12449: } ! 12450: ! 12451: p->iIndent = 0; ! 12452: sqlite3_free(abYield); ! 12453: sqlite3_reset(pSql); ! 12454: } ! 12455: ! 12456: /* ! 12457: ** Free the array allocated by explain_data_prepare(). ! 12458: */ ! 12459: static void explain_data_delete(ShellState *p){ ! 12460: sqlite3_free(p->aiIndent); ! 12461: p->aiIndent = 0; ! 12462: p->nIndent = 0; ! 12463: p->iIndent = 0; ! 12464: } ! 12465: ! 12466: /* ! 12467: ** Disable and restore .wheretrace and .selecttrace settings. ! 12468: */ ! 12469: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) ! 12470: extern unsigned int sqlite3_unsupported_selecttrace; ! 12471: static int savedSelectTrace; ! 12472: #endif ! 12473: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) ! 12474: extern int sqlite3WhereTrace; ! 12475: static int savedWhereTrace; ! 12476: #endif ! 12477: static void disable_debug_trace_modes(void){ ! 12478: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) ! 12479: savedSelectTrace = sqlite3_unsupported_selecttrace; ! 12480: sqlite3_unsupported_selecttrace = 0; ! 12481: #endif ! 12482: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) ! 12483: savedWhereTrace = sqlite3WhereTrace; ! 12484: sqlite3WhereTrace = 0; ! 12485: #endif ! 12486: } ! 12487: static void restore_debug_trace_modes(void){ ! 12488: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) ! 12489: sqlite3_unsupported_selecttrace = savedSelectTrace; ! 12490: #endif ! 12491: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) ! 12492: sqlite3WhereTrace = savedWhereTrace; ! 12493: #endif ! 12494: } ! 12495: ! 12496: /* Create the TEMP table used to store parameter bindings */ ! 12497: static void bind_table_init(ShellState *p){ ! 12498: int wrSchema = 0; ! 12499: int defensiveMode = 0; ! 12500: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode); ! 12501: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0); ! 12502: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); ! 12503: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); ! 12504: sqlite3_exec(p->db, ! 12505: "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n" ! 12506: " key TEXT PRIMARY KEY,\n" ! 12507: " value ANY\n" ! 12508: ") WITHOUT ROWID;", ! 12509: 0, 0, 0); ! 12510: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); ! 12511: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0); ! 12512: } ! 12513: ! 12514: /* ! 12515: ** Bind parameters on a prepared statement. ! 12516: ** ! 12517: ** Parameter bindings are taken from a TEMP table of the form: ! 12518: ** ! 12519: ** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value) ! 12520: ** WITHOUT ROWID; ! 12521: ** ! 12522: ** No bindings occur if this table does not exist. The name of the table ! 12523: ** begins with "sqlite_" so that it will not collide with ordinary application ! 12524: ** tables. The table must be in the TEMP schema. ! 12525: */ ! 12526: static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ ! 12527: int nVar; ! 12528: int i; ! 12529: int rc; ! 12530: sqlite3_stmt *pQ = 0; ! 12531: ! 12532: nVar = sqlite3_bind_parameter_count(pStmt); ! 12533: if( nVar==0 ) return; /* Nothing to do */ ! 12534: if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters", ! 12535: "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){ ! 12536: return; /* Parameter table does not exist */ ! 12537: } ! 12538: rc = sqlite3_prepare_v2(pArg->db, ! 12539: "SELECT value FROM temp.sqlite_parameters" ! 12540: " WHERE key=?1", -1, &pQ, 0); ! 12541: if( rc || pQ==0 ) return; ! 12542: for(i=1; i<=nVar; i++){ ! 12543: char zNum[30]; ! 12544: const char *zVar = sqlite3_bind_parameter_name(pStmt, i); ! 12545: if( zVar==0 ){ ! 12546: sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i); ! 12547: zVar = zNum; ! 12548: } ! 12549: sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC); ! 12550: if( sqlite3_step(pQ)==SQLITE_ROW ){ ! 12551: sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0)); ! 12552: }else{ ! 12553: sqlite3_bind_null(pStmt, i); ! 12554: } ! 12555: sqlite3_reset(pQ); ! 12556: } ! 12557: sqlite3_finalize(pQ); ! 12558: } ! 12559: ! 12560: /* ! 12561: ** UTF8 box-drawing characters. Imagine box lines like this: ! 12562: ** ! 12563: ** 1 ! 12564: ** | ! 12565: ** 4 --+-- 2 ! 12566: ** | ! 12567: ** 3 ! 12568: ** ! 12569: ** Each box characters has between 2 and 4 of the lines leading from ! 12570: ** the center. The characters are here identified by the numbers of ! 12571: ** their corresponding lines. ! 12572: */ ! 12573: #define BOX_24 "\342\224\200" /* U+2500 --- */ ! 12574: #define BOX_13 "\342\224\202" /* U+2502 | */ ! 12575: #define BOX_23 "\342\224\214" /* U+250c ,- */ ! 12576: #define BOX_34 "\342\224\220" /* U+2510 -, */ ! 12577: #define BOX_12 "\342\224\224" /* U+2514 '- */ ! 12578: #define BOX_14 "\342\224\230" /* U+2518 -' */ ! 12579: #define BOX_123 "\342\224\234" /* U+251c |- */ ! 12580: #define BOX_134 "\342\224\244" /* U+2524 -| */ ! 12581: #define BOX_234 "\342\224\254" /* U+252c -,- */ ! 12582: #define BOX_124 "\342\224\264" /* U+2534 -'- */ ! 12583: #define BOX_1234 "\342\224\274" /* U+253c -|- */ ! 12584: ! 12585: /* Draw horizontal line N characters long using unicode box ! 12586: ** characters ! 12587: */ ! 12588: static void print_box_line(FILE *out, int N){ ! 12589: const char zDash[] = ! 12590: BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 ! 12591: BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24; ! 12592: const int nDash = sizeof(zDash) - 1; ! 12593: N *= 3; ! 12594: while( N>nDash ){ ! 12595: utf8_printf(out, zDash); ! 12596: N -= nDash; ! 12597: } ! 12598: utf8_printf(out, "%.*s", N, zDash); ! 12599: } ! 12600: ! 12601: /* ! 12602: ** Draw a horizontal separator for a MODE_Box table. ! 12603: */ ! 12604: static void print_box_row_separator( ! 12605: ShellState *p, ! 12606: int nArg, ! 12607: const char *zSep1, ! 12608: const char *zSep2, ! 12609: const char *zSep3 ! 12610: ){ ! 12611: int i; ! 12612: if( nArg>0 ){ ! 12613: utf8_printf(p->out, "%s", zSep1); ! 12614: print_box_line(p->out, p->actualWidth[0]+2); ! 12615: for(i=1; i<nArg; i++){ ! 12616: utf8_printf(p->out, "%s", zSep2); ! 12617: print_box_line(p->out, p->actualWidth[i]+2); ! 12618: } ! 12619: utf8_printf(p->out, "%s", zSep3); ! 12620: } ! 12621: fputs("\n", p->out); ! 12622: } ! 12623: ! 12624: ! 12625: ! 12626: /* ! 12627: ** Run a prepared statement and output the result in one of the ! 12628: ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table, ! 12629: ** or MODE_Box. ! 12630: ** ! 12631: ** This is different from ordinary exec_prepared_stmt() in that ! 12632: ** it has to run the entire query and gather the results into memory ! 12633: ** first, in order to determine column widths, before providing ! 12634: ** any output. ! 12635: */ ! 12636: static void exec_prepared_stmt_columnar( ! 12637: ShellState *p, /* Pointer to ShellState */ ! 12638: sqlite3_stmt *pStmt /* Statment to run */ ! 12639: ){ ! 12640: sqlite3_int64 nRow = 0; ! 12641: int nColumn = 0; ! 12642: char **azData = 0; ! 12643: sqlite3_int64 nAlloc = 0; ! 12644: const char *z; ! 12645: int rc; ! 12646: sqlite3_int64 i, nData; ! 12647: int j, nTotal, w, n; ! 12648: const char *colSep = 0; ! 12649: const char *rowSep = 0; ! 12650: ! 12651: rc = sqlite3_step(pStmt); ! 12652: if( rc!=SQLITE_ROW ) return; ! 12653: nColumn = sqlite3_column_count(pStmt); ! 12654: nAlloc = nColumn*4; ! 12655: azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); ! 12656: if( azData==0 ) shell_out_of_memory(); ! 12657: for(i=0; i<nColumn; i++){ ! 12658: azData[i] = strdup(sqlite3_column_name(pStmt,i)); ! 12659: } ! 12660: do{ ! 12661: if( (nRow+2)*nColumn >= nAlloc ){ ! 12662: nAlloc *= 2; ! 12663: azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); ! 12664: if( azData==0 ) shell_out_of_memory(); ! 12665: } ! 12666: nRow++; ! 12667: for(i=0; i<nColumn; i++){ ! 12668: z = (const char*)sqlite3_column_text(pStmt,i); ! 12669: azData[nRow*nColumn + i] = z ? strdup(z) : 0; ! 12670: } ! 12671: }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ); ! 12672: if( nColumn>p->nWidth ){ ! 12673: p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int)); ! 12674: if( p->colWidth==0 ) shell_out_of_memory(); ! 12675: for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0; ! 12676: p->nWidth = nColumn; ! 12677: p->actualWidth = &p->colWidth[nColumn]; ! 12678: } ! 12679: memset(p->actualWidth, 0, nColumn*sizeof(int)); ! 12680: for(i=0; i<nColumn; i++){ ! 12681: w = p->colWidth[i]; ! 12682: if( w<0 ) w = -w; ! 12683: p->actualWidth[i] = w; ! 12684: } ! 12685: nTotal = nColumn*(nRow+1); ! 12686: for(i=0; i<nTotal; i++){ ! 12687: z = azData[i]; ! 12688: if( z==0 ) z = p->nullValue; ! 12689: n = strlenChar(z); ! 12690: j = i%nColumn; ! 12691: if( n>p->actualWidth[j] ) p->actualWidth[j] = n; ! 12692: } ! 12693: if( seenInterrupt ) goto columnar_end; ! 12694: switch( p->cMode ){ ! 12695: case MODE_Column: { ! 12696: colSep = " "; ! 12697: rowSep = "\n"; ! 12698: if( p->showHeader ){ ! 12699: for(i=0; i<nColumn; i++){ ! 12700: w = p->actualWidth[i]; ! 12701: if( p->colWidth[i]<0 ) w = -w; ! 12702: utf8_width_print(p->out, w, azData[i]); ! 12703: fputs(i==nColumn-1?"\n":" ", p->out); ! 12704: } ! 12705: for(i=0; i<nColumn; i++){ ! 12706: print_dashes(p->out, p->actualWidth[i]); ! 12707: fputs(i==nColumn-1?"\n":" ", p->out); ! 12708: } ! 12709: } ! 12710: break; ! 12711: } ! 12712: case MODE_Table: { ! 12713: colSep = " | "; ! 12714: rowSep = " |\n"; ! 12715: print_row_separator(p, nColumn, "+"); ! 12716: fputs("| ", p->out); ! 12717: for(i=0; i<nColumn; i++){ ! 12718: w = p->actualWidth[i]; ! 12719: n = strlenChar(azData[i]); ! 12720: utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); ! 12721: fputs(i==nColumn-1?" |\n":" | ", p->out); ! 12722: } ! 12723: print_row_separator(p, nColumn, "+"); ! 12724: break; ! 12725: } ! 12726: case MODE_Markdown: { ! 12727: colSep = " | "; ! 12728: rowSep = " |\n"; ! 12729: fputs("| ", p->out); ! 12730: for(i=0; i<nColumn; i++){ ! 12731: w = p->actualWidth[i]; ! 12732: n = strlenChar(azData[i]); ! 12733: utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); ! 12734: fputs(i==nColumn-1?" |\n":" | ", p->out); ! 12735: } ! 12736: print_row_separator(p, nColumn, "|"); ! 12737: break; ! 12738: } ! 12739: case MODE_Box: { ! 12740: colSep = " " BOX_13 " "; ! 12741: rowSep = " " BOX_13 "\n"; ! 12742: print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34); ! 12743: utf8_printf(p->out, BOX_13 " "); ! 12744: for(i=0; i<nColumn; i++){ ! 12745: w = p->actualWidth[i]; ! 12746: n = strlenChar(azData[i]); ! 12747: utf8_printf(p->out, "%*s%s%*s%s", ! 12748: (w-n)/2, "", azData[i], (w-n+1)/2, "", ! 12749: i==nColumn-1?" "BOX_13"\n":" "BOX_13" "); ! 12750: } ! 12751: print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); ! 12752: break; ! 12753: } ! 12754: } ! 12755: for(i=nColumn, j=0; i<nTotal; i++, j++){ ! 12756: if( j==0 && p->cMode!=MODE_Column ){ ! 12757: utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| "); ! 12758: } ! 12759: z = azData[i]; ! 12760: if( z==0 ) z = p->nullValue; ! 12761: w = p->actualWidth[j]; ! 12762: if( p->colWidth[j]<0 ) w = -w; ! 12763: utf8_width_print(p->out, w, z); ! 12764: if( j==nColumn-1 ){ ! 12765: utf8_printf(p->out, "%s", rowSep); ! 12766: j = -1; ! 12767: if( seenInterrupt ) goto columnar_end; ! 12768: }else{ ! 12769: utf8_printf(p->out, "%s", colSep); ! 12770: } ! 12771: } ! 12772: if( p->cMode==MODE_Table ){ ! 12773: print_row_separator(p, nColumn, "+"); ! 12774: }else if( p->cMode==MODE_Box ){ ! 12775: print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); ! 12776: } ! 12777: columnar_end: ! 12778: if( seenInterrupt ){ ! 12779: utf8_printf(p->out, "Interrupt\n"); ! 12780: } ! 12781: nData = (nRow+1)*nColumn; ! 12782: for(i=0; i<nData; i++) free(azData[i]); ! 12783: sqlite3_free(azData); ! 12784: } ! 12785: ! 12786: /* ! 12787: ** Run a prepared statement ! 12788: */ ! 12789: static void exec_prepared_stmt( ! 12790: ShellState *pArg, /* Pointer to ShellState */ ! 12791: sqlite3_stmt *pStmt /* Statment to run */ ! 12792: ){ ! 12793: int rc; ! 12794: ! 12795: if( pArg->cMode==MODE_Column ! 12796: || pArg->cMode==MODE_Table ! 12797: || pArg->cMode==MODE_Box ! 12798: || pArg->cMode==MODE_Markdown ! 12799: ){ ! 12800: exec_prepared_stmt_columnar(pArg, pStmt); ! 12801: return; ! 12802: } ! 12803: ! 12804: /* perform the first step. this will tell us if we ! 12805: ** have a result set or not and how wide it is. ! 12806: */ ! 12807: rc = sqlite3_step(pStmt); ! 12808: /* if we have a result set... */ ! 12809: if( SQLITE_ROW == rc ){ ! 12810: /* allocate space for col name ptr, value ptr, and type */ ! 12811: int nCol = sqlite3_column_count(pStmt); ! 12812: void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); ! 12813: if( !pData ){ ! 12814: rc = SQLITE_NOMEM; ! 12815: }else{ ! 12816: char **azCols = (char **)pData; /* Names of result columns */ ! 12817: char **azVals = &azCols[nCol]; /* Results */ ! 12818: int *aiTypes = (int *)&azVals[nCol]; /* Result types */ ! 12819: int i, x; ! 12820: assert(sizeof(int) <= sizeof(char *)); ! 12821: /* save off ptrs to column names */ ! 12822: for(i=0; i<nCol; i++){ ! 12823: azCols[i] = (char *)sqlite3_column_name(pStmt, i); ! 12824: } ! 12825: do{ ! 12826: /* extract the data and data types */ ! 12827: for(i=0; i<nCol; i++){ ! 12828: aiTypes[i] = x = sqlite3_column_type(pStmt, i); ! 12829: if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ ! 12830: azVals[i] = ""; ! 12831: }else{ ! 12832: azVals[i] = (char*)sqlite3_column_text(pStmt, i); ! 12833: } ! 12834: if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ ! 12835: rc = SQLITE_NOMEM; ! 12836: break; /* from for */ ! 12837: } ! 12838: } /* end for */ ! 12839: ! 12840: /* if data and types extracted successfully... */ ! 12841: if( SQLITE_ROW == rc ){ ! 12842: /* call the supplied callback with the result row data */ ! 12843: if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){ ! 12844: rc = SQLITE_ABORT; ! 12845: }else{ ! 12846: rc = sqlite3_step(pStmt); ! 12847: } ! 12848: } ! 12849: } while( SQLITE_ROW == rc ); ! 12850: sqlite3_free(pData); ! 12851: if( pArg->cMode==MODE_Json ){ ! 12852: fputs("]\n", pArg->out); ! 12853: } ! 12854: } ! 12855: } ! 12856: } ! 12857: ! 12858: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 12859: /* ! 12860: ** This function is called to process SQL if the previous shell command ! 12861: ** was ".expert". It passes the SQL in the second argument directly to ! 12862: ** the sqlite3expert object. ! 12863: ** ! 12864: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ! 12865: ** code. In this case, (*pzErr) may be set to point to a buffer containing ! 12866: ** an English language error message. It is the responsibility of the ! 12867: ** caller to eventually free this buffer using sqlite3_free(). ! 12868: */ ! 12869: static int expertHandleSQL( ! 12870: ShellState *pState, ! 12871: const char *zSql, ! 12872: char **pzErr ! 12873: ){ ! 12874: assert( pState->expert.pExpert ); ! 12875: assert( pzErr==0 || *pzErr==0 ); ! 12876: return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr); ! 12877: } ! 12878: ! 12879: /* ! 12880: ** This function is called either to silently clean up the object ! 12881: ** created by the ".expert" command (if bCancel==1), or to generate a ! 12882: ** report from it and then clean it up (if bCancel==0). ! 12883: ** ! 12884: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ! 12885: ** code. In this case, (*pzErr) may be set to point to a buffer containing ! 12886: ** an English language error message. It is the responsibility of the ! 12887: ** caller to eventually free this buffer using sqlite3_free(). ! 12888: */ ! 12889: static int expertFinish( ! 12890: ShellState *pState, ! 12891: int bCancel, ! 12892: char **pzErr ! 12893: ){ ! 12894: int rc = SQLITE_OK; ! 12895: sqlite3expert *p = pState->expert.pExpert; ! 12896: assert( p ); ! 12897: assert( bCancel || pzErr==0 || *pzErr==0 ); ! 12898: if( bCancel==0 ){ ! 12899: FILE *out = pState->out; ! 12900: int bVerbose = pState->expert.bVerbose; ! 12901: ! 12902: rc = sqlite3_expert_analyze(p, pzErr); ! 12903: if( rc==SQLITE_OK ){ ! 12904: int nQuery = sqlite3_expert_count(p); ! 12905: int i; ! 12906: ! 12907: if( bVerbose ){ ! 12908: const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES); ! 12909: raw_printf(out, "-- Candidates -----------------------------\n"); ! 12910: raw_printf(out, "%s\n", zCand); ! 12911: } ! 12912: for(i=0; i<nQuery; i++){ ! 12913: const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL); ! 12914: const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES); ! 12915: const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN); ! 12916: if( zIdx==0 ) zIdx = "(no new indexes)\n"; ! 12917: if( bVerbose ){ ! 12918: raw_printf(out, "-- Query %d --------------------------------\n",i+1); ! 12919: raw_printf(out, "%s\n\n", zSql); ! 12920: } ! 12921: raw_printf(out, "%s\n", zIdx); ! 12922: raw_printf(out, "%s\n", zEQP); ! 12923: } ! 12924: } ! 12925: } ! 12926: sqlite3_expert_destroy(p); ! 12927: pState->expert.pExpert = 0; ! 12928: return rc; ! 12929: } ! 12930: ! 12931: /* ! 12932: ** Implementation of ".expert" dot command. ! 12933: */ ! 12934: static int expertDotCommand( ! 12935: ShellState *pState, /* Current shell tool state */ ! 12936: char **azArg, /* Array of arguments passed to dot command */ ! 12937: int nArg /* Number of entries in azArg[] */ ! 12938: ){ ! 12939: int rc = SQLITE_OK; ! 12940: char *zErr = 0; ! 12941: int i; ! 12942: int iSample = 0; ! 12943: ! 12944: assert( pState->expert.pExpert==0 ); ! 12945: memset(&pState->expert, 0, sizeof(ExpertInfo)); ! 12946: ! 12947: for(i=1; rc==SQLITE_OK && i<nArg; i++){ ! 12948: char *z = azArg[i]; ! 12949: int n; ! 12950: if( z[0]=='-' && z[1]=='-' ) z++; ! 12951: n = strlen30(z); ! 12952: if( n>=2 && 0==strncmp(z, "-verbose", n) ){ ! 12953: pState->expert.bVerbose = 1; ! 12954: } ! 12955: else if( n>=2 && 0==strncmp(z, "-sample", n) ){ ! 12956: if( i==(nArg-1) ){ ! 12957: raw_printf(stderr, "option requires an argument: %s\n", z); ! 12958: rc = SQLITE_ERROR; ! 12959: }else{ ! 12960: iSample = (int)integerValue(azArg[++i]); ! 12961: if( iSample<0 || iSample>100 ){ ! 12962: raw_printf(stderr, "value out of range: %s\n", azArg[i]); ! 12963: rc = SQLITE_ERROR; ! 12964: } ! 12965: } ! 12966: } ! 12967: else{ ! 12968: raw_printf(stderr, "unknown option: %s\n", z); ! 12969: rc = SQLITE_ERROR; ! 12970: } ! 12971: } ! 12972: ! 12973: if( rc==SQLITE_OK ){ ! 12974: pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); ! 12975: if( pState->expert.pExpert==0 ){ ! 12976: raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); ! 12977: rc = SQLITE_ERROR; ! 12978: }else{ ! 12979: sqlite3_expert_config( ! 12980: pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample ! 12981: ); ! 12982: } ! 12983: } ! 12984: ! 12985: return rc; ! 12986: } ! 12987: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ ! 12988: ! 12989: /* ! 12990: ** Execute a statement or set of statements. Print ! 12991: ** any result rows/columns depending on the current mode ! 12992: ** set via the supplied callback. ! 12993: ** ! 12994: ** This is very similar to SQLite's built-in sqlite3_exec() ! 12995: ** function except it takes a slightly different callback ! 12996: ** and callback data argument. ! 12997: */ ! 12998: static int shell_exec( ! 12999: ShellState *pArg, /* Pointer to ShellState */ ! 13000: const char *zSql, /* SQL to be evaluated */ ! 13001: char **pzErrMsg /* Error msg written here */ ! 13002: ){ ! 13003: sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ ! 13004: int rc = SQLITE_OK; /* Return Code */ ! 13005: int rc2; ! 13006: const char *zLeftover; /* Tail of unprocessed SQL */ ! 13007: sqlite3 *db = pArg->db; ! 13008: ! 13009: if( pzErrMsg ){ ! 13010: *pzErrMsg = NULL; ! 13011: } ! 13012: ! 13013: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 13014: if( pArg->expert.pExpert ){ ! 13015: rc = expertHandleSQL(pArg, zSql, pzErrMsg); ! 13016: return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); ! 13017: } ! 13018: #endif ! 13019: ! 13020: while( zSql[0] && (SQLITE_OK == rc) ){ ! 13021: static const char *zStmtSql; ! 13022: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); ! 13023: if( SQLITE_OK != rc ){ ! 13024: if( pzErrMsg ){ ! 13025: *pzErrMsg = save_err_msg(db); ! 13026: } ! 13027: }else{ ! 13028: if( !pStmt ){ ! 13029: /* this happens for a comment or white-space */ ! 13030: zSql = zLeftover; ! 13031: while( IsSpace(zSql[0]) ) zSql++; ! 13032: continue; ! 13033: } ! 13034: zStmtSql = sqlite3_sql(pStmt); ! 13035: if( zStmtSql==0 ) zStmtSql = ""; ! 13036: while( IsSpace(zStmtSql[0]) ) zStmtSql++; ! 13037: ! 13038: /* save off the prepared statment handle and reset row count */ ! 13039: if( pArg ){ ! 13040: pArg->pStmt = pStmt; ! 13041: pArg->cnt = 0; ! 13042: } ! 13043: ! 13044: /* echo the sql statement if echo on */ ! 13045: if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){ ! 13046: utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); ! 13047: } ! 13048: ! 13049: /* Show the EXPLAIN QUERY PLAN if .eqp is on */ ! 13050: if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){ ! 13051: sqlite3_stmt *pExplain; ! 13052: char *zEQP; ! 13053: int triggerEQP = 0; ! 13054: disable_debug_trace_modes(); ! 13055: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); ! 13056: if( pArg->autoEQP>=AUTOEQP_trigger ){ ! 13057: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); ! 13058: } ! 13059: zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); ! 13060: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); ! 13061: if( rc==SQLITE_OK ){ ! 13062: while( sqlite3_step(pExplain)==SQLITE_ROW ){ ! 13063: const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); ! 13064: int iEqpId = sqlite3_column_int(pExplain, 0); ! 13065: int iParentId = sqlite3_column_int(pExplain, 1); ! 13066: if( zEQPLine==0 ) zEQPLine = ""; ! 13067: if( zEQPLine[0]=='-' ) eqp_render(pArg); ! 13068: eqp_append(pArg, iEqpId, iParentId, zEQPLine); ! 13069: } ! 13070: eqp_render(pArg); ! 13071: } ! 13072: sqlite3_finalize(pExplain); ! 13073: sqlite3_free(zEQP); ! 13074: if( pArg->autoEQP>=AUTOEQP_full ){ ! 13075: /* Also do an EXPLAIN for ".eqp full" mode */ ! 13076: zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); ! 13077: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); ! 13078: if( rc==SQLITE_OK ){ ! 13079: pArg->cMode = MODE_Explain; ! 13080: explain_data_prepare(pArg, pExplain); ! 13081: exec_prepared_stmt(pArg, pExplain); ! 13082: explain_data_delete(pArg); ! 13083: } ! 13084: sqlite3_finalize(pExplain); ! 13085: sqlite3_free(zEQP); ! 13086: } ! 13087: if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ ! 13088: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); ! 13089: /* Reprepare pStmt before reactiving trace modes */ ! 13090: sqlite3_finalize(pStmt); ! 13091: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ! 13092: if( pArg ) pArg->pStmt = pStmt; ! 13093: } ! 13094: restore_debug_trace_modes(); ! 13095: } ! 13096: ! 13097: if( pArg ){ ! 13098: pArg->cMode = pArg->mode; ! 13099: if( pArg->autoExplain ){ ! 13100: if( sqlite3_stmt_isexplain(pStmt)==1 ){ ! 13101: pArg->cMode = MODE_Explain; ! 13102: } ! 13103: if( sqlite3_stmt_isexplain(pStmt)==2 ){ ! 13104: pArg->cMode = MODE_EQP; ! 13105: } ! 13106: } ! 13107: ! 13108: /* If the shell is currently in ".explain" mode, gather the extra ! 13109: ** data required to add indents to the output.*/ ! 13110: if( pArg->cMode==MODE_Explain ){ ! 13111: explain_data_prepare(pArg, pStmt); ! 13112: } ! 13113: } ! 13114: ! 13115: bind_prepared_stmt(pArg, pStmt); ! 13116: exec_prepared_stmt(pArg, pStmt); ! 13117: explain_data_delete(pArg); ! 13118: eqp_render(pArg); ! 13119: ! 13120: /* print usage stats if stats on */ ! 13121: if( pArg && pArg->statsOn ){ ! 13122: display_stats(db, pArg, 0); ! 13123: } ! 13124: ! 13125: /* print loop-counters if required */ ! 13126: if( pArg && pArg->scanstatsOn ){ ! 13127: display_scanstats(db, pArg); ! 13128: } ! 13129: ! 13130: /* Finalize the statement just executed. If this fails, save a ! 13131: ** copy of the error message. Otherwise, set zSql to point to the ! 13132: ** next statement to execute. */ ! 13133: rc2 = sqlite3_finalize(pStmt); ! 13134: if( rc!=SQLITE_NOMEM ) rc = rc2; ! 13135: if( rc==SQLITE_OK ){ ! 13136: zSql = zLeftover; ! 13137: while( IsSpace(zSql[0]) ) zSql++; ! 13138: }else if( pzErrMsg ){ ! 13139: *pzErrMsg = save_err_msg(db); ! 13140: } ! 13141: ! 13142: /* clear saved stmt handle */ ! 13143: if( pArg ){ ! 13144: pArg->pStmt = NULL; ! 13145: } ! 13146: } ! 13147: } /* end while */ ! 13148: ! 13149: return rc; ! 13150: } ! 13151: ! 13152: /* ! 13153: ** Release memory previously allocated by tableColumnList(). ! 13154: */ ! 13155: static void freeColumnList(char **azCol){ ! 13156: int i; ! 13157: for(i=1; azCol[i]; i++){ ! 13158: sqlite3_free(azCol[i]); ! 13159: } ! 13160: /* azCol[0] is a static string */ ! 13161: sqlite3_free(azCol); ! 13162: } ! 13163: ! 13164: /* ! 13165: ** Return a list of pointers to strings which are the names of all ! 13166: ** columns in table zTab. The memory to hold the names is dynamically ! 13167: ** allocated and must be released by the caller using a subsequent call ! 13168: ** to freeColumnList(). ! 13169: ** ! 13170: ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid ! 13171: ** value that needs to be preserved, then azCol[0] is filled in with the ! 13172: ** name of the rowid column. ! 13173: ** ! 13174: ** The first regular column in the table is azCol[1]. The list is terminated ! 13175: ** by an entry with azCol[i]==0. ! 13176: */ ! 13177: static char **tableColumnList(ShellState *p, const char *zTab){ ! 13178: char **azCol = 0; ! 13179: sqlite3_stmt *pStmt; ! 13180: char *zSql; ! 13181: int nCol = 0; ! 13182: int nAlloc = 0; ! 13183: int nPK = 0; /* Number of PRIMARY KEY columns seen */ ! 13184: int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ ! 13185: int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid); ! 13186: int rc; ! 13187: ! 13188: zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); ! 13189: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 13190: sqlite3_free(zSql); ! 13191: if( rc ) return 0; ! 13192: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 13193: if( nCol>=nAlloc-2 ){ ! 13194: nAlloc = nAlloc*2 + nCol + 10; ! 13195: azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); ! 13196: if( azCol==0 ) shell_out_of_memory(); ! 13197: } ! 13198: azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); ! 13199: if( sqlite3_column_int(pStmt, 5) ){ ! 13200: nPK++; ! 13201: if( nPK==1 ! 13202: && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), ! 13203: "INTEGER")==0 ! 13204: ){ ! 13205: isIPK = 1; ! 13206: }else{ ! 13207: isIPK = 0; ! 13208: } ! 13209: } ! 13210: } ! 13211: sqlite3_finalize(pStmt); ! 13212: if( azCol==0 ) return 0; ! 13213: azCol[0] = 0; ! 13214: azCol[nCol+1] = 0; ! 13215: ! 13216: /* The decision of whether or not a rowid really needs to be preserved ! 13217: ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table ! 13218: ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve ! 13219: ** rowids on tables where the rowid is inaccessible because there are other ! 13220: ** columns in the table named "rowid", "_rowid_", and "oid". ! 13221: */ ! 13222: if( preserveRowid && isIPK ){ ! 13223: /* If a single PRIMARY KEY column with type INTEGER was seen, then it ! 13224: ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID ! 13225: ** table or a INTEGER PRIMARY KEY DESC column, neither of which are ! 13226: ** ROWID aliases. To distinguish these cases, check to see if ! 13227: ** there is a "pk" entry in "PRAGMA index_list". There will be ! 13228: ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID. ! 13229: */ ! 13230: zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" ! 13231: " WHERE origin='pk'", zTab); ! 13232: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 13233: sqlite3_free(zSql); ! 13234: if( rc ){ ! 13235: freeColumnList(azCol); ! 13236: return 0; ! 13237: } ! 13238: rc = sqlite3_step(pStmt); ! 13239: sqlite3_finalize(pStmt); ! 13240: preserveRowid = rc==SQLITE_ROW; ! 13241: } ! 13242: if( preserveRowid ){ ! 13243: /* Only preserve the rowid if we can find a name to use for the ! 13244: ** rowid */ ! 13245: static char *azRowid[] = { "rowid", "_rowid_", "oid" }; ! 13246: int i, j; ! 13247: for(j=0; j<3; j++){ ! 13248: for(i=1; i<=nCol; i++){ ! 13249: if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; ! 13250: } ! 13251: if( i>nCol ){ ! 13252: /* At this point, we know that azRowid[j] is not the name of any ! 13253: ** ordinary column in the table. Verify that azRowid[j] is a valid ! 13254: ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID ! 13255: ** tables will fail this last check */ ! 13256: rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); ! 13257: if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; ! 13258: break; ! 13259: } ! 13260: } ! 13261: } ! 13262: return azCol; ! 13263: } ! 13264: ! 13265: /* ! 13266: ** Toggle the reverse_unordered_selects setting. ! 13267: */ ! 13268: static void toggleSelectOrder(sqlite3 *db){ ! 13269: sqlite3_stmt *pStmt = 0; ! 13270: int iSetting = 0; ! 13271: char zStmt[100]; ! 13272: sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0); ! 13273: if( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 13274: iSetting = sqlite3_column_int(pStmt, 0); ! 13275: } ! 13276: sqlite3_finalize(pStmt); ! 13277: sqlite3_snprintf(sizeof(zStmt), zStmt, ! 13278: "PRAGMA reverse_unordered_selects(%d)", !iSetting); ! 13279: sqlite3_exec(db, zStmt, 0, 0, 0); ! 13280: } ! 13281: ! 13282: /* ! 13283: ** This is a different callback routine used for dumping the database. ! 13284: ** Each row received by this callback consists of a table name, ! 13285: ** the table type ("index" or "table") and SQL to create the table. ! 13286: ** This routine should print text sufficient to recreate the table. ! 13287: */ ! 13288: static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){ ! 13289: int rc; ! 13290: const char *zTable; ! 13291: const char *zType; ! 13292: const char *zSql; ! 13293: ShellState *p = (ShellState *)pArg; ! 13294: ! 13295: UNUSED_PARAMETER(azNotUsed); ! 13296: if( nArg!=3 || azArg==0 ) return 0; ! 13297: zTable = azArg[0]; ! 13298: zType = azArg[1]; ! 13299: zSql = azArg[2]; ! 13300: ! 13301: if( strcmp(zTable, "sqlite_sequence")==0 ){ ! 13302: raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); ! 13303: }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){ ! 13304: raw_printf(p->out, "ANALYZE sqlite_schema;\n"); ! 13305: }else if( strncmp(zTable, "sqlite_", 7)==0 ){ ! 13306: return 0; ! 13307: }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ ! 13308: char *zIns; ! 13309: if( !p->writableSchema ){ ! 13310: raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); ! 13311: p->writableSchema = 1; ! 13312: } ! 13313: zIns = sqlite3_mprintf( ! 13314: "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)" ! 13315: "VALUES('table','%q','%q',0,'%q');", ! 13316: zTable, zTable, zSql); ! 13317: utf8_printf(p->out, "%s\n", zIns); ! 13318: sqlite3_free(zIns); ! 13319: return 0; ! 13320: }else{ ! 13321: printSchemaLine(p->out, zSql, ";\n"); ! 13322: } ! 13323: ! 13324: if( strcmp(zType, "table")==0 ){ ! 13325: ShellText sSelect; ! 13326: ShellText sTable; ! 13327: char **azCol; ! 13328: int i; ! 13329: char *savedDestTable; ! 13330: int savedMode; ! 13331: ! 13332: azCol = tableColumnList(p, zTable); ! 13333: if( azCol==0 ){ ! 13334: p->nErr++; ! 13335: return 0; ! 13336: } ! 13337: ! 13338: /* Always quote the table name, even if it appears to be pure ascii, ! 13339: ** in case it is a keyword. Ex: INSERT INTO "table" ... */ ! 13340: initText(&sTable); ! 13341: appendText(&sTable, zTable, quoteChar(zTable)); ! 13342: /* If preserving the rowid, add a column list after the table name. ! 13343: ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)" ! 13344: ** instead of the usual "INSERT INTO tab VALUES(...)". ! 13345: */ ! 13346: if( azCol[0] ){ ! 13347: appendText(&sTable, "(", 0); ! 13348: appendText(&sTable, azCol[0], 0); ! 13349: for(i=1; azCol[i]; i++){ ! 13350: appendText(&sTable, ",", 0); ! 13351: appendText(&sTable, azCol[i], quoteChar(azCol[i])); ! 13352: } ! 13353: appendText(&sTable, ")", 0); ! 13354: } ! 13355: ! 13356: /* Build an appropriate SELECT statement */ ! 13357: initText(&sSelect); ! 13358: appendText(&sSelect, "SELECT ", 0); ! 13359: if( azCol[0] ){ ! 13360: appendText(&sSelect, azCol[0], 0); ! 13361: appendText(&sSelect, ",", 0); ! 13362: } ! 13363: for(i=1; azCol[i]; i++){ ! 13364: appendText(&sSelect, azCol[i], quoteChar(azCol[i])); ! 13365: if( azCol[i+1] ){ ! 13366: appendText(&sSelect, ",", 0); ! 13367: } ! 13368: } ! 13369: freeColumnList(azCol); ! 13370: appendText(&sSelect, " FROM ", 0); ! 13371: appendText(&sSelect, zTable, quoteChar(zTable)); ! 13372: ! 13373: savedDestTable = p->zDestTable; ! 13374: savedMode = p->mode; ! 13375: p->zDestTable = sTable.z; ! 13376: p->mode = p->cMode = MODE_Insert; ! 13377: rc = shell_exec(p, sSelect.z, 0); ! 13378: if( (rc&0xff)==SQLITE_CORRUPT ){ ! 13379: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); ! 13380: toggleSelectOrder(p->db); ! 13381: shell_exec(p, sSelect.z, 0); ! 13382: toggleSelectOrder(p->db); ! 13383: } ! 13384: p->zDestTable = savedDestTable; ! 13385: p->mode = savedMode; ! 13386: freeText(&sTable); ! 13387: freeText(&sSelect); ! 13388: if( rc ) p->nErr++; ! 13389: } ! 13390: return 0; ! 13391: } ! 13392: ! 13393: /* ! 13394: ** Run zQuery. Use dump_callback() as the callback routine so that ! 13395: ** the contents of the query are output as SQL statements. ! 13396: ** ! 13397: ** If we get a SQLITE_CORRUPT error, rerun the query after appending ! 13398: ** "ORDER BY rowid DESC" to the end. ! 13399: */ ! 13400: static int run_schema_dump_query( ! 13401: ShellState *p, ! 13402: const char *zQuery ! 13403: ){ ! 13404: int rc; ! 13405: char *zErr = 0; ! 13406: rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); ! 13407: if( rc==SQLITE_CORRUPT ){ ! 13408: char *zQ2; ! 13409: int len = strlen30(zQuery); ! 13410: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); ! 13411: if( zErr ){ ! 13412: utf8_printf(p->out, "/****** %s ******/\n", zErr); ! 13413: sqlite3_free(zErr); ! 13414: zErr = 0; ! 13415: } ! 13416: zQ2 = malloc( len+100 ); ! 13417: if( zQ2==0 ) return rc; ! 13418: sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); ! 13419: rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); ! 13420: if( rc ){ ! 13421: utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr); ! 13422: }else{ ! 13423: rc = SQLITE_CORRUPT; ! 13424: } ! 13425: sqlite3_free(zErr); ! 13426: free(zQ2); ! 13427: } ! 13428: return rc; ! 13429: } ! 13430: ! 13431: /* ! 13432: ** Text of help messages. ! 13433: ** ! 13434: ** The help text for each individual command begins with a line that starts ! 13435: ** with ".". Subsequent lines are supplimental information. ! 13436: ** ! 13437: ** There must be two or more spaces between the end of the command and the ! 13438: ** start of the description of what that command does. ! 13439: */ ! 13440: static const char *(azHelp[]) = { ! 13441: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) ! 13442: ".archive ... Manage SQL archives", ! 13443: " Each command must have exactly one of the following options:", ! 13444: " -c, --create Create a new archive", ! 13445: " -u, --update Add or update files with changed mtime", ! 13446: " -i, --insert Like -u but always add even if unchanged", ! 13447: " -t, --list List contents of archive", ! 13448: " -x, --extract Extract files from archive", ! 13449: " Optional arguments:", ! 13450: " -v, --verbose Print each filename as it is processed", ! 13451: " -f FILE, --file FILE Use archive FILE (default is current db)", ! 13452: " -a FILE, --append FILE Open FILE using the apndvfs VFS", ! 13453: " -C DIR, --directory DIR Read/extract files from directory DIR", ! 13454: " -n, --dryrun Show the SQL that would have occurred", ! 13455: " Examples:", ! 13456: " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", ! 13457: " .ar -tf ARCHIVE # List members of ARCHIVE", ! 13458: " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", ! 13459: " See also:", ! 13460: " http://sqlite.org/cli.html#sqlar_archive_support", ! 13461: #endif ! 13462: #ifndef SQLITE_OMIT_AUTHORIZATION ! 13463: ".auth ON|OFF Show authorizer callbacks", ! 13464: #endif ! 13465: ".backup ?DB? FILE Backup DB (default \"main\") to FILE", ! 13466: " --append Use the appendvfs", ! 13467: " --async Write to FILE without journal and fsync()", ! 13468: ".bail on|off Stop after hitting an error. Default OFF", ! 13469: ".binary on|off Turn binary output on or off. Default OFF", ! 13470: ".cd DIRECTORY Change the working directory to DIRECTORY", ! 13471: ".changes on|off Show number of rows changed by SQL", ! 13472: ".check GLOB Fail if output since .testcase does not match", ! 13473: ".clone NEWDB Clone data into NEWDB from the existing database", ! 13474: ".databases List names and files of attached databases", ! 13475: ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ! 13476: ".dbinfo ?DB? Show status information about the database", ! 13477: ".dump ?TABLE? Render database content as SQL", ! 13478: " Options:", ! 13479: " --preserve-rowids Include ROWID values in the output", ! 13480: " --newlines Allow unescaped newline characters in output", ! 13481: " TABLE is a LIKE pattern for the tables to dump", ! 13482: " Additional LIKE patterns can be given in subsequent arguments", ! 13483: ".echo on|off Turn command echo on or off", ! 13484: ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", ! 13485: " Other Modes:", ! 13486: #ifdef SQLITE_DEBUG ! 13487: " test Show raw EXPLAIN QUERY PLAN output", ! 13488: " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", ! 13489: #endif ! 13490: " trigger Like \"full\" but also show trigger bytecode", ! 13491: ".excel Display the output of next command in spreadsheet", ! 13492: " --bom Put a UTF8 byte-order mark on intermediate file", ! 13493: ".exit ?CODE? Exit this program with return-code CODE", ! 13494: ".expert EXPERIMENTAL. Suggest indexes for queries", ! 13495: ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", ! 13496: ".filectrl CMD ... Run various sqlite3_file_control() operations", ! 13497: " --schema SCHEMA Use SCHEMA instead of \"main\"", ! 13498: " --help Show CMD details", ! 13499: ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ! 13500: ".headers on|off Turn display of headers on or off", ! 13501: ".help ?-all? ?PATTERN? Show help text for PATTERN", ! 13502: ".import FILE TABLE Import data from FILE into TABLE", ! 13503: " Options:", ! 13504: " --ascii Use \\037 and \\036 as column and row separators", ! 13505: " --csv Use , and \\n as column and row separators", ! 13506: " --skip N Skip the first N rows of input", ! 13507: " -v \"Verbose\" - increase auxiliary output", ! 13508: " Notes:", ! 13509: " * If TABLE does not exist, it is created. The first row of input", ! 13510: " determines the column names.", ! 13511: " * If neither --csv or --ascii are used, the input mode is derived", ! 13512: " from the \".mode\" output mode", ! 13513: " * If FILE begins with \"|\" then it is a command that generates the", ! 13514: " input text.", ! 13515: #ifndef SQLITE_OMIT_TEST_CONTROL ! 13516: ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", ! 13517: #endif ! 13518: ".indexes ?TABLE? Show names of indexes", ! 13519: " If TABLE is specified, only show indexes for", ! 13520: " tables matching TABLE using the LIKE operator.", ! 13521: #ifdef SQLITE_ENABLE_IOTRACE ! 13522: ".iotrace FILE Enable I/O diagnostic logging to FILE", ! 13523: #endif ! 13524: ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", ! 13525: ".lint OPTIONS Report potential schema issues.", ! 13526: " Options:", ! 13527: " fkey-indexes Find missing foreign key indexes", ! 13528: #ifndef SQLITE_OMIT_LOAD_EXTENSION ! 13529: ".load FILE ?ENTRY? Load an extension library", ! 13530: #endif ! 13531: ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", ! 13532: ".mode MODE ?TABLE? Set output mode", ! 13533: " MODE is one of:", ! 13534: " ascii Columns/rows delimited by 0x1F and 0x1E", ! 13535: " box Tables using unicode box-drawing characters", ! 13536: " csv Comma-separated values", ! 13537: " column Output in columns. (See .width)", ! 13538: " html HTML <table> code", ! 13539: " insert SQL insert statements for TABLE", ! 13540: " json Results in a JSON array", ! 13541: " line One value per line", ! 13542: " list Values delimited by \"|\"", ! 13543: " markdown Markdown table format", ! 13544: " quote Escape answers as for SQL", ! 13545: " table ASCII-art table", ! 13546: " tabs Tab-separated values", ! 13547: " tcl TCL list elements", ! 13548: ".nullvalue STRING Use STRING in place of NULL values", ! 13549: ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", ! 13550: " If FILE begins with '|' then open as a pipe", ! 13551: " --bom Put a UTF8 byte-order mark at the beginning", ! 13552: " -e Send output to the system text editor", ! 13553: " -x Send output as CSV to a spreadsheet (same as \".excel\")", ! 13554: #ifdef SQLITE_DEBUG ! 13555: ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", ! 13556: #endif ! 13557: ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", ! 13558: " Options:", ! 13559: " --append Use appendvfs to append database to the end of FILE", ! 13560: #ifdef SQLITE_ENABLE_DESERIALIZE ! 13561: " --deserialize Load into memory useing sqlite3_deserialize()", ! 13562: " --hexdb Load the output of \"dbtotxt\" as an in-memory db", ! 13563: " --maxsize N Maximum size for --hexdb or --deserialized database", ! 13564: #endif ! 13565: " --new Initialize FILE to an empty database", ! 13566: " --nofollow Do not follow symbolic links", ! 13567: " --readonly Open FILE readonly", ! 13568: " --zip FILE is a ZIP archive", ! 13569: ".output ?FILE? Send output to FILE or stdout if FILE is omitted", ! 13570: " If FILE begins with '|' then open it as a pipe.", ! 13571: " Options:", ! 13572: " --bom Prefix output with a UTF8 byte-order mark", ! 13573: " -e Send output to the system text editor", ! 13574: " -x Send output as CSV to a spreadsheet", ! 13575: ".parameter CMD ... Manage SQL parameter bindings", ! 13576: " clear Erase all bindings", ! 13577: " init Initialize the TEMP table that holds bindings", ! 13578: " list List the current parameter bindings", ! 13579: " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", ! 13580: " PARAMETER should start with one of: $ : @ ?", ! 13581: " unset PARAMETER Remove PARAMETER from the binding table", ! 13582: ".print STRING... Print literal STRING", ! 13583: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK ! 13584: ".progress N Invoke progress handler after every N opcodes", ! 13585: " --limit N Interrupt after N progress callbacks", ! 13586: " --once Do no more than one progress interrupt", ! 13587: " --quiet|-q No output except at interrupts", ! 13588: " --reset Reset the count for each input and interrupt", ! 13589: #endif ! 13590: ".prompt MAIN CONTINUE Replace the standard prompts", ! 13591: ".quit Exit this program", ! 13592: ".read FILE Read input from FILE", ! 13593: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ! 13594: ".recover Recover as much data as possible from corrupt db.", ! 13595: " --freelist-corrupt Assume the freelist is corrupt", ! 13596: " --recovery-db NAME Store recovery metadata in database file NAME", ! 13597: " --lost-and-found TABLE Alternative name for the lost-and-found table", ! 13598: " --no-rowids Do not attempt to recover rowid values", ! 13599: " that are not also INTEGER PRIMARY KEYs", ! 13600: #endif ! 13601: ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ! 13602: ".save FILE Write in-memory database into FILE", ! 13603: ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", ! 13604: ".schema ?PATTERN? Show the CREATE statements matching PATTERN", ! 13605: " Options:", ! 13606: " --indent Try to pretty-print the schema", ! 13607: ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", ! 13608: " Options:", ! 13609: " --init Create a new SELFTEST table", ! 13610: " -v Verbose output", ! 13611: ".separator COL ?ROW? Change the column and row separators", ! 13612: #if defined(SQLITE_ENABLE_SESSION) ! 13613: ".session ?NAME? CMD ... Create or control sessions", ! 13614: " Subcommands:", ! 13615: " attach TABLE Attach TABLE", ! 13616: " changeset FILE Write a changeset into FILE", ! 13617: " close Close one session", ! 13618: " enable ?BOOLEAN? Set or query the enable bit", ! 13619: " filter GLOB... Reject tables matching GLOBs", ! 13620: " indirect ?BOOLEAN? Mark or query the indirect status", ! 13621: " isempty Query whether the session is empty", ! 13622: " list List currently open session names", ! 13623: " open DB NAME Open a new session on DB", ! 13624: " patchset FILE Write a patchset into FILE", ! 13625: " If ?NAME? is omitted, the first defined session is used.", ! 13626: #endif ! 13627: ".sha3sum ... Compute a SHA3 hash of database content", ! 13628: " Options:", ! 13629: " --schema Also hash the sqlite_schema table", ! 13630: " --sha3-224 Use the sha3-224 algorithm", ! 13631: " --sha3-256 Use the sha3-256 algorithm (default)", ! 13632: " --sha3-384 Use the sha3-384 algorithm", ! 13633: " --sha3-512 Use the sha3-512 algorithm", ! 13634: " Any other argument is a LIKE pattern for tables to hash", ! 13635: #ifndef SQLITE_NOHAVE_SYSTEM ! 13636: ".shell CMD ARGS... Run CMD ARGS... in a system shell", ! 13637: #endif ! 13638: ".show Show the current values for various settings", ! 13639: ".stats ?on|off? Show stats or turn stats on or off", ! 13640: #ifndef SQLITE_NOHAVE_SYSTEM ! 13641: ".system CMD ARGS... Run CMD ARGS... in a system shell", ! 13642: #endif ! 13643: ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", ! 13644: ".testcase NAME Begin redirecting output to 'testcase-out.txt'", ! 13645: ".testctrl CMD ... Run various sqlite3_test_control() operations", ! 13646: " Run \".testctrl\" with no arguments for details", ! 13647: ".timeout MS Try opening locked tables for MS milliseconds", ! 13648: ".timer on|off Turn SQL timer on or off", ! 13649: #ifndef SQLITE_OMIT_TRACE ! 13650: ".trace ?OPTIONS? Output each SQL statement as it is run", ! 13651: " FILE Send output to FILE", ! 13652: " stdout Send output to stdout", ! 13653: " stderr Send output to stderr", ! 13654: " off Disable tracing", ! 13655: " --expanded Expand query parameters", ! 13656: #ifdef SQLITE_ENABLE_NORMALIZE ! 13657: " --normalized Normal the SQL statements", ! 13658: #endif ! 13659: " --plain Show SQL as it is input", ! 13660: " --stmt Trace statement execution (SQLITE_TRACE_STMT)", ! 13661: " --profile Profile statements (SQLITE_TRACE_PROFILE)", ! 13662: " --row Trace each row (SQLITE_TRACE_ROW)", ! 13663: " --close Trace connection close (SQLITE_TRACE_CLOSE)", ! 13664: #endif /* SQLITE_OMIT_TRACE */ ! 13665: #ifdef SQLITE_DEBUG ! 13666: ".unmodule NAME ... Unregister virtual table modules", ! 13667: " --allexcept Unregister everything except those named", ! 13668: #endif ! 13669: ".vfsinfo ?AUX? Information about the top-level VFS", ! 13670: ".vfslist List all available VFSes", ! 13671: ".vfsname ?AUX? Print the name of the VFS stack", ! 13672: ".width NUM1 NUM2 ... Set minimum column widths for columnar output", ! 13673: " Negative values right-justify", ! 13674: }; ! 13675: ! 13676: /* ! 13677: ** Output help text. ! 13678: ** ! 13679: ** zPattern describes the set of commands for which help text is provided. ! 13680: ** If zPattern is NULL, then show all commands, but only give a one-line ! 13681: ** description of each. ! 13682: ** ! 13683: ** Return the number of matches. ! 13684: */ ! 13685: static int showHelp(FILE *out, const char *zPattern){ ! 13686: int i = 0; ! 13687: int j = 0; ! 13688: int n = 0; ! 13689: char *zPat; ! 13690: if( zPattern==0 ! 13691: || zPattern[0]=='0' ! 13692: || strcmp(zPattern,"-a")==0 ! 13693: || strcmp(zPattern,"-all")==0 ! 13694: || strcmp(zPattern,"--all")==0 ! 13695: ){ ! 13696: /* Show all commands, but only one line per command */ ! 13697: if( zPattern==0 ) zPattern = ""; ! 13698: for(i=0; i<ArraySize(azHelp); i++){ ! 13699: if( azHelp[i][0]=='.' || zPattern[0] ){ ! 13700: utf8_printf(out, "%s\n", azHelp[i]); ! 13701: n++; ! 13702: } ! 13703: } ! 13704: }else{ ! 13705: /* Look for commands that for which zPattern is an exact prefix */ ! 13706: zPat = sqlite3_mprintf(".%s*", zPattern); ! 13707: for(i=0; i<ArraySize(azHelp); i++){ ! 13708: if( sqlite3_strglob(zPat, azHelp[i])==0 ){ ! 13709: utf8_printf(out, "%s\n", azHelp[i]); ! 13710: j = i+1; ! 13711: n++; ! 13712: } ! 13713: } ! 13714: sqlite3_free(zPat); ! 13715: if( n ){ ! 13716: if( n==1 ){ ! 13717: /* when zPattern is a prefix of exactly one command, then include the ! 13718: ** details of that command, which should begin at offset j */ ! 13719: while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){ ! 13720: utf8_printf(out, "%s\n", azHelp[j]); ! 13721: j++; ! 13722: } ! 13723: } ! 13724: return n; ! 13725: } ! 13726: /* Look for commands that contain zPattern anywhere. Show the complete ! 13727: ** text of all commands that match. */ ! 13728: zPat = sqlite3_mprintf("%%%s%%", zPattern); ! 13729: for(i=0; i<ArraySize(azHelp); i++){ ! 13730: if( azHelp[i][0]=='.' ) j = i; ! 13731: if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){ ! 13732: utf8_printf(out, "%s\n", azHelp[j]); ! 13733: while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){ ! 13734: j++; ! 13735: utf8_printf(out, "%s\n", azHelp[j]); ! 13736: } ! 13737: i = j; ! 13738: n++; ! 13739: } ! 13740: } ! 13741: sqlite3_free(zPat); ! 13742: } ! 13743: return n; ! 13744: } ! 13745: ! 13746: /* Forward reference */ ! 13747: static int process_input(ShellState *p); ! 13748: ! 13749: /* ! 13750: ** Read the content of file zName into memory obtained from sqlite3_malloc64() ! 13751: ** and return a pointer to the buffer. The caller is responsible for freeing ! 13752: ** the memory. ! 13753: ** ! 13754: ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes ! 13755: ** read. ! 13756: ** ! 13757: ** For convenience, a nul-terminator byte is always appended to the data read ! 13758: ** from the file before the buffer is returned. This byte is not included in ! 13759: ** the final value of (*pnByte), if applicable. ! 13760: ** ! 13761: ** NULL is returned if any error is encountered. The final value of *pnByte ! 13762: ** is undefined in this case. ! 13763: */ ! 13764: static char *readFile(const char *zName, int *pnByte){ ! 13765: FILE *in = fopen(zName, "rb"); ! 13766: long nIn; ! 13767: size_t nRead; ! 13768: char *pBuf; ! 13769: if( in==0 ) return 0; ! 13770: fseek(in, 0, SEEK_END); ! 13771: nIn = ftell(in); ! 13772: rewind(in); ! 13773: pBuf = sqlite3_malloc64( nIn+1 ); ! 13774: if( pBuf==0 ){ fclose(in); return 0; } ! 13775: nRead = fread(pBuf, nIn, 1, in); ! 13776: fclose(in); ! 13777: if( nRead!=1 ){ ! 13778: sqlite3_free(pBuf); ! 13779: return 0; ! 13780: } ! 13781: pBuf[nIn] = 0; ! 13782: if( pnByte ) *pnByte = nIn; ! 13783: return pBuf; ! 13784: } ! 13785: ! 13786: #if defined(SQLITE_ENABLE_SESSION) ! 13787: /* ! 13788: ** Close a single OpenSession object and release all of its associated ! 13789: ** resources. ! 13790: */ ! 13791: static void session_close(OpenSession *pSession){ ! 13792: int i; ! 13793: sqlite3session_delete(pSession->p); ! 13794: sqlite3_free(pSession->zName); ! 13795: for(i=0; i<pSession->nFilter; i++){ ! 13796: sqlite3_free(pSession->azFilter[i]); ! 13797: } ! 13798: sqlite3_free(pSession->azFilter); ! 13799: memset(pSession, 0, sizeof(OpenSession)); ! 13800: } ! 13801: #endif ! 13802: ! 13803: /* ! 13804: ** Close all OpenSession objects and release all associated resources. ! 13805: */ ! 13806: #if defined(SQLITE_ENABLE_SESSION) ! 13807: static void session_close_all(ShellState *p){ ! 13808: int i; ! 13809: for(i=0; i<p->nSession; i++){ ! 13810: session_close(&p->aSession[i]); ! 13811: } ! 13812: p->nSession = 0; ! 13813: } ! 13814: #else ! 13815: # define session_close_all(X) ! 13816: #endif ! 13817: ! 13818: /* ! 13819: ** Implementation of the xFilter function for an open session. Omit ! 13820: ** any tables named by ".session filter" but let all other table through. ! 13821: */ ! 13822: #if defined(SQLITE_ENABLE_SESSION) ! 13823: static int session_filter(void *pCtx, const char *zTab){ ! 13824: OpenSession *pSession = (OpenSession*)pCtx; ! 13825: int i; ! 13826: for(i=0; i<pSession->nFilter; i++){ ! 13827: if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; ! 13828: } ! 13829: return 1; ! 13830: } ! 13831: #endif ! 13832: ! 13833: /* ! 13834: ** Try to deduce the type of file for zName based on its content. Return ! 13835: ** one of the SHELL_OPEN_* constants. ! 13836: ** ! 13837: ** If the file does not exist or is empty but its name looks like a ZIP ! 13838: ** archive and the dfltZip flag is true, then assume it is a ZIP archive. ! 13839: ** Otherwise, assume an ordinary database regardless of the filename if ! 13840: ** the type cannot be determined from content. ! 13841: */ ! 13842: int deduceDatabaseType(const char *zName, int dfltZip){ ! 13843: FILE *f = fopen(zName, "rb"); ! 13844: size_t n; ! 13845: int rc = SHELL_OPEN_UNSPEC; ! 13846: char zBuf[100]; ! 13847: if( f==0 ){ ! 13848: if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ ! 13849: return SHELL_OPEN_ZIPFILE; ! 13850: }else{ ! 13851: return SHELL_OPEN_NORMAL; ! 13852: } ! 13853: } ! 13854: n = fread(zBuf, 16, 1, f); ! 13855: if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ ! 13856: fclose(f); ! 13857: return SHELL_OPEN_NORMAL; ! 13858: } ! 13859: fseek(f, -25, SEEK_END); ! 13860: n = fread(zBuf, 25, 1, f); ! 13861: if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ ! 13862: rc = SHELL_OPEN_APPENDVFS; ! 13863: }else{ ! 13864: fseek(f, -22, SEEK_END); ! 13865: n = fread(zBuf, 22, 1, f); ! 13866: if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05 ! 13867: && zBuf[3]==0x06 ){ ! 13868: rc = SHELL_OPEN_ZIPFILE; ! 13869: }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ ! 13870: rc = SHELL_OPEN_ZIPFILE; ! 13871: } ! 13872: } ! 13873: fclose(f); ! 13874: return rc; ! 13875: } ! 13876: ! 13877: #ifdef SQLITE_ENABLE_DESERIALIZE ! 13878: /* ! 13879: ** Reconstruct an in-memory database using the output from the "dbtotxt" ! 13880: ** program. Read content from the file in p->zDbFilename. If p->zDbFilename ! 13881: ** is 0, then read from standard input. ! 13882: */ ! 13883: static unsigned char *readHexDb(ShellState *p, int *pnData){ ! 13884: unsigned char *a = 0; ! 13885: int nLine; ! 13886: int n = 0; ! 13887: int pgsz = 0; ! 13888: int iOffset = 0; ! 13889: int j, k; ! 13890: int rc; ! 13891: FILE *in; ! 13892: unsigned int x[16]; ! 13893: char zLine[1000]; ! 13894: if( p->zDbFilename ){ ! 13895: in = fopen(p->zDbFilename, "r"); ! 13896: if( in==0 ){ ! 13897: utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename); ! 13898: return 0; ! 13899: } ! 13900: nLine = 0; ! 13901: }else{ ! 13902: in = p->in; ! 13903: nLine = p->lineno; ! 13904: if( in==0 ) in = stdin; ! 13905: } ! 13906: *pnData = 0; ! 13907: nLine++; ! 13908: if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; ! 13909: rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); ! 13910: if( rc!=2 ) goto readHexDb_error; ! 13911: if( n<0 ) goto readHexDb_error; ! 13912: if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error; ! 13913: n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ ! 13914: a = sqlite3_malloc( n ? n : 1 ); ! 13915: if( a==0 ){ ! 13916: utf8_printf(stderr, "Out of memory!\n"); ! 13917: goto readHexDb_error; ! 13918: } ! 13919: memset(a, 0, n); ! 13920: if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){ ! 13921: utf8_printf(stderr, "invalid pagesize\n"); ! 13922: goto readHexDb_error; ! 13923: } ! 13924: for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){ ! 13925: rc = sscanf(zLine, "| page %d offset %d", &j, &k); ! 13926: if( rc==2 ){ ! 13927: iOffset = k; ! 13928: continue; ! 13929: } ! 13930: if( strncmp(zLine, "| end ", 6)==0 ){ ! 13931: break; ! 13932: } ! 13933: rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", ! 13934: &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], ! 13935: &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]); ! 13936: if( rc==17 ){ ! 13937: k = iOffset+j; ! 13938: if( k+16<=n ){ ! 13939: int ii; ! 13940: for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff; ! 13941: } ! 13942: } ! 13943: } ! 13944: *pnData = n; ! 13945: if( in!=p->in ){ ! 13946: fclose(in); ! 13947: }else{ ! 13948: p->lineno = nLine; ! 13949: } ! 13950: return a; ! 13951: ! 13952: readHexDb_error: ! 13953: if( in!=p->in ){ ! 13954: fclose(in); ! 13955: }else{ ! 13956: while( fgets(zLine, sizeof(zLine), p->in)!=0 ){ ! 13957: nLine++; ! 13958: if(strncmp(zLine, "| end ", 6)==0 ) break; ! 13959: } ! 13960: p->lineno = nLine; ! 13961: } ! 13962: sqlite3_free(a); ! 13963: utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); ! 13964: return 0; ! 13965: } ! 13966: #endif /* SQLITE_ENABLE_DESERIALIZE */ ! 13967: ! 13968: /* ! 13969: ** Scalar function "shell_int32". The first argument to this function ! 13970: ** must be a blob. The second a non-negative integer. This function ! 13971: ** reads and returns a 32-bit big-endian integer from byte ! 13972: ** offset (4*<arg2>) of the blob. ! 13973: */ ! 13974: static void shellInt32( ! 13975: sqlite3_context *context, ! 13976: int argc, ! 13977: sqlite3_value **argv ! 13978: ){ ! 13979: const unsigned char *pBlob; ! 13980: int nBlob; ! 13981: int iInt; ! 13982: ! 13983: UNUSED_PARAMETER(argc); ! 13984: nBlob = sqlite3_value_bytes(argv[0]); ! 13985: pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]); ! 13986: iInt = sqlite3_value_int(argv[1]); ! 13987: ! 13988: if( iInt>=0 && (iInt+1)*4<=nBlob ){ ! 13989: const unsigned char *a = &pBlob[iInt*4]; ! 13990: sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24) ! 13991: + ((sqlite3_int64)a[1]<<16) ! 13992: + ((sqlite3_int64)a[2]<< 8) ! 13993: + ((sqlite3_int64)a[3]<< 0); ! 13994: sqlite3_result_int64(context, iVal); ! 13995: } ! 13996: } ! 13997: ! 13998: /* ! 13999: ** Scalar function "shell_idquote(X)" returns string X quoted as an identifier, ! 14000: ** using "..." with internal double-quote characters doubled. ! 14001: */ ! 14002: static void shellIdQuote( ! 14003: sqlite3_context *context, ! 14004: int argc, ! 14005: sqlite3_value **argv ! 14006: ){ ! 14007: const char *zName = (const char*)sqlite3_value_text(argv[0]); ! 14008: UNUSED_PARAMETER(argc); ! 14009: if( zName ){ ! 14010: char *z = sqlite3_mprintf("\"%w\"", zName); ! 14011: sqlite3_result_text(context, z, -1, sqlite3_free); ! 14012: } ! 14013: } ! 14014: ! 14015: /* ! 14016: ** Scalar function "shell_escape_crnl" used by the .recover command. ! 14017: ** The argument passed to this function is the output of built-in ! 14018: ** function quote(). If the first character of the input is "'", ! 14019: ** indicating that the value passed to quote() was a text value, ! 14020: ** then this function searches the input for "\n" and "\r" characters ! 14021: ** and adds a wrapper similar to the following: ! 14022: ** ! 14023: ** replace(replace(<input>, '\n', char(10), '\r', char(13)); ! 14024: ** ! 14025: ** Or, if the first character of the input is not "'", then a copy ! 14026: ** of the input is returned. ! 14027: */ ! 14028: static void shellEscapeCrnl( ! 14029: sqlite3_context *context, ! 14030: int argc, ! 14031: sqlite3_value **argv ! 14032: ){ ! 14033: const char *zText = (const char*)sqlite3_value_text(argv[0]); ! 14034: UNUSED_PARAMETER(argc); ! 14035: if( zText[0]=='\'' ){ ! 14036: int nText = sqlite3_value_bytes(argv[0]); ! 14037: int i; ! 14038: char zBuf1[20]; ! 14039: char zBuf2[20]; ! 14040: const char *zNL = 0; ! 14041: const char *zCR = 0; ! 14042: int nCR = 0; ! 14043: int nNL = 0; ! 14044: ! 14045: for(i=0; zText[i]; i++){ ! 14046: if( zNL==0 && zText[i]=='\n' ){ ! 14047: zNL = unused_string(zText, "\\n", "\\012", zBuf1); ! 14048: nNL = (int)strlen(zNL); ! 14049: } ! 14050: if( zCR==0 && zText[i]=='\r' ){ ! 14051: zCR = unused_string(zText, "\\r", "\\015", zBuf2); ! 14052: nCR = (int)strlen(zCR); ! 14053: } ! 14054: } ! 14055: ! 14056: if( zNL || zCR ){ ! 14057: int iOut = 0; ! 14058: i64 nMax = (nNL > nCR) ? nNL : nCR; ! 14059: i64 nAlloc = nMax * nText + (nMax+64)*2; ! 14060: char *zOut = (char*)sqlite3_malloc64(nAlloc); ! 14061: if( zOut==0 ){ ! 14062: sqlite3_result_error_nomem(context); ! 14063: return; ! 14064: } ! 14065: ! 14066: if( zNL && zCR ){ ! 14067: memcpy(&zOut[iOut], "replace(replace(", 16); ! 14068: iOut += 16; ! 14069: }else{ ! 14070: memcpy(&zOut[iOut], "replace(", 8); ! 14071: iOut += 8; ! 14072: } ! 14073: for(i=0; zText[i]; i++){ ! 14074: if( zText[i]=='\n' ){ ! 14075: memcpy(&zOut[iOut], zNL, nNL); ! 14076: iOut += nNL; ! 14077: }else if( zText[i]=='\r' ){ ! 14078: memcpy(&zOut[iOut], zCR, nCR); ! 14079: iOut += nCR; 1.3 misho 14080: }else{ 1.5 ! misho 14081: zOut[iOut] = zText[i]; ! 14082: iOut++; 1.4 misho 14083: } 14084: } 1.5 ! misho 14085: ! 14086: if( zNL ){ ! 14087: memcpy(&zOut[iOut], ",'", 2); iOut += 2; ! 14088: memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; ! 14089: memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12; ! 14090: } ! 14091: if( zCR ){ ! 14092: memcpy(&zOut[iOut], ",'", 2); iOut += 2; ! 14093: memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; ! 14094: memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12; ! 14095: } ! 14096: ! 14097: sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT); ! 14098: sqlite3_free(zOut); ! 14099: return; 1.4 misho 14100: } 1.5 ! misho 14101: } ! 14102: ! 14103: sqlite3_result_value(context, argv[0]); ! 14104: } ! 14105: ! 14106: /* Flags for open_db(). ! 14107: ** ! 14108: ** The default behavior of open_db() is to exit(1) if the database fails to ! 14109: ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error ! 14110: ** but still returns without calling exit. ! 14111: ** ! 14112: ** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a ! 14113: ** ZIP archive if the file does not exist or is empty and its name matches ! 14114: ** the *.zip pattern. ! 14115: */ ! 14116: #define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */ ! 14117: #define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */ ! 14118: ! 14119: /* ! 14120: ** Make sure the database is open. If it is not, then open it. If ! 14121: ** the database fails to open, print an error message and exit. ! 14122: */ ! 14123: static void open_db(ShellState *p, int openFlags){ ! 14124: if( p->db==0 ){ ! 14125: if( p->openMode==SHELL_OPEN_UNSPEC ){ ! 14126: if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){ ! 14127: p->openMode = SHELL_OPEN_NORMAL; ! 14128: }else{ ! 14129: p->openMode = (u8)deduceDatabaseType(p->zDbFilename, ! 14130: (openFlags & OPEN_DB_ZIPFILE)!=0); ! 14131: } 1.4 misho 14132: } 1.5 ! misho 14133: switch( p->openMode ){ ! 14134: case SHELL_OPEN_APPENDVFS: { ! 14135: sqlite3_open_v2(p->zDbFilename, &p->db, ! 14136: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs"); ! 14137: break; ! 14138: } ! 14139: case SHELL_OPEN_HEXDB: ! 14140: case SHELL_OPEN_DESERIALIZE: { ! 14141: sqlite3_open(0, &p->db); ! 14142: break; ! 14143: } ! 14144: case SHELL_OPEN_ZIPFILE: { ! 14145: sqlite3_open(":memory:", &p->db); ! 14146: break; ! 14147: } ! 14148: case SHELL_OPEN_READONLY: { ! 14149: sqlite3_open_v2(p->zDbFilename, &p->db, ! 14150: SQLITE_OPEN_READONLY|p->openFlags, 0); 1.4 misho 14151: break; 14152: } 1.5 ! misho 14153: case SHELL_OPEN_UNSPEC: ! 14154: case SHELL_OPEN_NORMAL: { ! 14155: sqlite3_open_v2(p->zDbFilename, &p->db, ! 14156: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0); ! 14157: break; 1.4 misho 14158: } 1.5 ! misho 14159: } ! 14160: globalDb = p->db; ! 14161: if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ ! 14162: utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", ! 14163: p->zDbFilename, sqlite3_errmsg(p->db)); ! 14164: if( openFlags & OPEN_DB_KEEPALIVE ){ ! 14165: sqlite3_open(":memory:", &p->db); ! 14166: return; 1.2 misho 14167: } 1.5 ! misho 14168: exit(1); 1.2 misho 14169: } 1.5 ! misho 14170: #ifndef SQLITE_OMIT_LOAD_EXTENSION ! 14171: sqlite3_enable_load_extension(p->db, 1); ! 14172: #endif ! 14173: sqlite3_fileio_init(p->db, 0, 0); ! 14174: sqlite3_shathree_init(p->db, 0, 0); ! 14175: sqlite3_completion_init(p->db, 0, 0); ! 14176: sqlite3_uint_init(p->db, 0, 0); ! 14177: sqlite3_decimal_init(p->db, 0, 0); ! 14178: sqlite3_ieee_init(p->db, 0, 0); ! 14179: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ! 14180: sqlite3_dbdata_init(p->db, 0, 0); ! 14181: #endif ! 14182: #ifdef SQLITE_HAVE_ZLIB ! 14183: sqlite3_zipfile_init(p->db, 0, 0); ! 14184: sqlite3_sqlar_init(p->db, 0, 0); ! 14185: #endif ! 14186: sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, ! 14187: shellAddSchemaName, 0, 0); ! 14188: sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, ! 14189: shellModuleSchema, 0, 0); ! 14190: sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, ! 14191: shellPutsFunc, 0, 0); ! 14192: sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0, ! 14193: shellEscapeCrnl, 0, 0); ! 14194: sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, ! 14195: shellInt32, 0, 0); ! 14196: sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0, ! 14197: shellIdQuote, 0, 0); ! 14198: #ifndef SQLITE_NOHAVE_SYSTEM ! 14199: sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, ! 14200: editFunc, 0, 0); ! 14201: sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, ! 14202: editFunc, 0, 0); ! 14203: #endif ! 14204: if( p->openMode==SHELL_OPEN_ZIPFILE ){ ! 14205: char *zSql = sqlite3_mprintf( ! 14206: "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); ! 14207: sqlite3_exec(p->db, zSql, 0, 0, 0); ! 14208: sqlite3_free(zSql); ! 14209: } ! 14210: #ifdef SQLITE_ENABLE_DESERIALIZE ! 14211: else ! 14212: if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){ ! 14213: int rc; ! 14214: int nData = 0; ! 14215: unsigned char *aData; ! 14216: if( p->openMode==SHELL_OPEN_DESERIALIZE ){ ! 14217: aData = (unsigned char*)readFile(p->zDbFilename, &nData); ! 14218: }else{ ! 14219: aData = readHexDb(p, &nData); ! 14220: if( aData==0 ){ ! 14221: return; 1.2 misho 14222: } 14223: } 1.5 ! misho 14224: rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, ! 14225: SQLITE_DESERIALIZE_RESIZEABLE | ! 14226: SQLITE_DESERIALIZE_FREEONCLOSE); ! 14227: if( rc ){ ! 14228: utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); ! 14229: } ! 14230: if( p->szMax>0 ){ ! 14231: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax); ! 14232: } ! 14233: } ! 14234: #endif ! 14235: } ! 14236: } ! 14237: ! 14238: /* ! 14239: ** Attempt to close the databaes connection. Report errors. ! 14240: */ ! 14241: void close_db(sqlite3 *db){ ! 14242: int rc = sqlite3_close(db); ! 14243: if( rc ){ ! 14244: utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", ! 14245: rc, sqlite3_errmsg(db)); ! 14246: } ! 14247: } ! 14248: ! 14249: #if HAVE_READLINE || HAVE_EDITLINE ! 14250: /* ! 14251: ** Readline completion callbacks ! 14252: */ ! 14253: static char *readline_completion_generator(const char *text, int state){ ! 14254: static sqlite3_stmt *pStmt = 0; ! 14255: char *zRet; ! 14256: if( state==0 ){ ! 14257: char *zSql; ! 14258: sqlite3_finalize(pStmt); ! 14259: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" ! 14260: " FROM completion(%Q) ORDER BY 1", text); ! 14261: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); ! 14262: sqlite3_free(zSql); ! 14263: } ! 14264: if( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 14265: zRet = strdup((const char*)sqlite3_column_text(pStmt, 0)); ! 14266: }else{ ! 14267: sqlite3_finalize(pStmt); ! 14268: pStmt = 0; ! 14269: zRet = 0; ! 14270: } ! 14271: return zRet; ! 14272: } ! 14273: static char **readline_completion(const char *zText, int iStart, int iEnd){ ! 14274: rl_attempted_completion_over = 1; ! 14275: return rl_completion_matches(zText, readline_completion_generator); ! 14276: } ! 14277: ! 14278: #elif HAVE_LINENOISE ! 14279: /* ! 14280: ** Linenoise completion callback ! 14281: */ ! 14282: static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ ! 14283: int nLine = strlen30(zLine); ! 14284: int i, iStart; ! 14285: sqlite3_stmt *pStmt = 0; ! 14286: char *zSql; ! 14287: char zBuf[1000]; ! 14288: ! 14289: if( nLine>sizeof(zBuf)-30 ) return; ! 14290: if( zLine[0]=='.' || zLine[0]=='#') return; ! 14291: for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){} ! 14292: if( i==nLine-1 ) return; ! 14293: iStart = i+1; ! 14294: memcpy(zBuf, zLine, iStart); ! 14295: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" ! 14296: " FROM completion(%Q,%Q) ORDER BY 1", ! 14297: &zLine[iStart], zLine); ! 14298: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); ! 14299: sqlite3_free(zSql); ! 14300: sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ ! 14301: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 14302: const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0); ! 14303: int nCompletion = sqlite3_column_bytes(pStmt, 0); ! 14304: if( iStart+nCompletion < sizeof(zBuf)-1 ){ ! 14305: memcpy(zBuf+iStart, zCompletion, nCompletion+1); ! 14306: linenoiseAddCompletion(lc, zBuf); ! 14307: } ! 14308: } ! 14309: sqlite3_finalize(pStmt); ! 14310: } ! 14311: #endif ! 14312: ! 14313: /* ! 14314: ** Do C-language style dequoting. ! 14315: ** ! 14316: ** \a -> alarm ! 14317: ** \b -> backspace ! 14318: ** \t -> tab ! 14319: ** \n -> newline ! 14320: ** \v -> vertical tab ! 14321: ** \f -> form feed ! 14322: ** \r -> carriage return ! 14323: ** \s -> space ! 14324: ** \" -> " ! 14325: ** \' -> ' ! 14326: ** \\ -> backslash ! 14327: ** \NNN -> ascii character NNN in octal ! 14328: */ ! 14329: static void resolve_backslashes(char *z){ ! 14330: int i, j; ! 14331: char c; ! 14332: while( *z && *z!='\\' ) z++; ! 14333: for(i=j=0; (c = z[i])!=0; i++, j++){ ! 14334: if( c=='\\' && z[i+1]!=0 ){ ! 14335: c = z[++i]; ! 14336: if( c=='a' ){ ! 14337: c = '\a'; ! 14338: }else if( c=='b' ){ ! 14339: c = '\b'; ! 14340: }else if( c=='t' ){ ! 14341: c = '\t'; ! 14342: }else if( c=='n' ){ ! 14343: c = '\n'; ! 14344: }else if( c=='v' ){ ! 14345: c = '\v'; ! 14346: }else if( c=='f' ){ ! 14347: c = '\f'; ! 14348: }else if( c=='r' ){ ! 14349: c = '\r'; ! 14350: }else if( c=='"' ){ ! 14351: c = '"'; ! 14352: }else if( c=='\'' ){ ! 14353: c = '\''; ! 14354: }else if( c=='\\' ){ ! 14355: c = '\\'; ! 14356: }else if( c>='0' && c<='7' ){ ! 14357: c -= '0'; ! 14358: if( z[i+1]>='0' && z[i+1]<='7' ){ ! 14359: i++; ! 14360: c = (c<<3) + z[i] - '0'; ! 14361: if( z[i+1]>='0' && z[i+1]<='7' ){ ! 14362: i++; ! 14363: c = (c<<3) + z[i] - '0'; ! 14364: } 1.2 misho 14365: } 14366: } 14367: } 1.5 ! misho 14368: z[j] = c; ! 14369: } ! 14370: if( j<i ) z[j] = 0; ! 14371: } ! 14372: ! 14373: /* ! 14374: ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 ! 14375: ** for TRUE and FALSE. Return the integer value if appropriate. ! 14376: */ ! 14377: static int booleanValue(const char *zArg){ ! 14378: int i; ! 14379: if( zArg[0]=='0' && zArg[1]=='x' ){ ! 14380: for(i=2; hexDigitValue(zArg[i])>=0; i++){} ! 14381: }else{ ! 14382: for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} ! 14383: } ! 14384: if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); ! 14385: if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ ! 14386: return 1; ! 14387: } ! 14388: if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ ! 14389: return 0; ! 14390: } ! 14391: utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", ! 14392: zArg); ! 14393: return 0; ! 14394: } ! 14395: ! 14396: /* ! 14397: ** Set or clear a shell flag according to a boolean value. ! 14398: */ ! 14399: static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){ ! 14400: if( booleanValue(zArg) ){ ! 14401: ShellSetFlag(p, mFlag); ! 14402: }else{ ! 14403: ShellClearFlag(p, mFlag); ! 14404: } ! 14405: } ! 14406: ! 14407: /* ! 14408: ** Close an output file, assuming it is not stderr or stdout ! 14409: */ ! 14410: static void output_file_close(FILE *f){ ! 14411: if( f && f!=stdout && f!=stderr ) fclose(f); ! 14412: } ! 14413: ! 14414: /* ! 14415: ** Try to open an output file. The names "stdout" and "stderr" are ! 14416: ** recognized and do the right thing. NULL is returned if the output ! 14417: ** filename is "off". ! 14418: */ ! 14419: static FILE *output_file_open(const char *zFile, int bTextMode){ ! 14420: FILE *f; ! 14421: if( strcmp(zFile,"stdout")==0 ){ ! 14422: f = stdout; ! 14423: }else if( strcmp(zFile, "stderr")==0 ){ ! 14424: f = stderr; ! 14425: }else if( strcmp(zFile, "off")==0 ){ ! 14426: f = 0; ! 14427: }else{ ! 14428: f = fopen(zFile, bTextMode ? "w" : "wb"); ! 14429: if( f==0 ){ ! 14430: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); 1.2 misho 14431: } 1.5 ! misho 14432: } ! 14433: return f; ! 14434: } ! 14435: ! 14436: #ifndef SQLITE_OMIT_TRACE ! 14437: /* ! 14438: ** A routine for handling output from sqlite3_trace(). ! 14439: */ ! 14440: static int sql_trace_callback( ! 14441: unsigned mType, /* The trace type */ ! 14442: void *pArg, /* The ShellState pointer */ ! 14443: void *pP, /* Usually a pointer to sqlite_stmt */ ! 14444: void *pX /* Auxiliary output */ ! 14445: ){ ! 14446: ShellState *p = (ShellState*)pArg; ! 14447: sqlite3_stmt *pStmt; ! 14448: const char *zSql; ! 14449: int nSql; ! 14450: if( p->traceOut==0 ) return 0; ! 14451: if( mType==SQLITE_TRACE_CLOSE ){ ! 14452: utf8_printf(p->traceOut, "-- closing database connection\n"); ! 14453: return 0; ! 14454: } ! 14455: if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){ ! 14456: zSql = (const char*)pX; ! 14457: }else{ ! 14458: pStmt = (sqlite3_stmt*)pP; ! 14459: switch( p->eTraceType ){ ! 14460: case SHELL_TRACE_EXPANDED: { ! 14461: zSql = sqlite3_expanded_sql(pStmt); ! 14462: break; 1.2 misho 14463: } 1.5 ! misho 14464: #ifdef SQLITE_ENABLE_NORMALIZE ! 14465: case SHELL_TRACE_NORMALIZED: { ! 14466: zSql = sqlite3_normalized_sql(pStmt); ! 14467: break; 1.2 misho 14468: } 1.5 ! misho 14469: #endif ! 14470: default: { ! 14471: zSql = sqlite3_sql(pStmt); ! 14472: break; 1.2 misho 14473: } 14474: } 1.5 ! misho 14475: } ! 14476: if( zSql==0 ) return 0; ! 14477: nSql = strlen30(zSql); ! 14478: while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; } ! 14479: switch( mType ){ ! 14480: case SQLITE_TRACE_ROW: ! 14481: case SQLITE_TRACE_STMT: { ! 14482: utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql); 1.4 misho 14483: break; 14484: } 1.5 ! misho 14485: case SQLITE_TRACE_PROFILE: { ! 14486: sqlite3_int64 nNanosec = *(sqlite3_int64*)pX; ! 14487: utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec); 1.2 misho 14488: break; 14489: } 14490: } 14491: return 0; 14492: } 1.5 ! misho 14493: #endif 1.2 misho 14494: 14495: /* 1.5 ! misho 14496: ** A no-op routine that runs with the ".breakpoint" doc-command. This is ! 14497: ** a useful spot to set a debugger breakpoint. 1.2 misho 14498: */ 1.5 ! misho 14499: static void test_breakpoint(void){ ! 14500: static int nCall = 0; ! 14501: nCall++; 1.2 misho 14502: } 14503: 14504: /* 1.5 ! misho 14505: ** An object used to read a CSV and other files for import. 1.2 misho 14506: */ 1.5 ! misho 14507: typedef struct ImportCtx ImportCtx; ! 14508: struct ImportCtx { ! 14509: const char *zFile; /* Name of the input file */ ! 14510: FILE *in; /* Read the CSV text from this input stream */ ! 14511: int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ ! 14512: char *z; /* Accumulated text for a field */ ! 14513: int n; /* Number of bytes in z */ ! 14514: int nAlloc; /* Space allocated for z[] */ ! 14515: int nLine; /* Current line number */ ! 14516: int nRow; /* Number of rows imported */ ! 14517: int nErr; /* Number of errors encountered */ ! 14518: int bNotFirst; /* True if one or more bytes already read */ ! 14519: int cTerm; /* Character that terminated the most recent field */ ! 14520: int cColSep; /* The column separator character. (Usually ",") */ ! 14521: int cRowSep; /* The row separator character. (Usually "\n") */ ! 14522: }; 1.2 misho 14523: 1.5 ! misho 14524: /* Clean up resourced used by an ImportCtx */ ! 14525: static void import_cleanup(ImportCtx *p){ ! 14526: if( p->in!=0 && p->xCloser!=0 ){ ! 14527: p->xCloser(p->in); ! 14528: p->in = 0; 1.2 misho 14529: } 1.5 ! misho 14530: sqlite3_free(p->z); ! 14531: p->z = 0; ! 14532: } ! 14533: ! 14534: /* Append a single byte to z[] */ ! 14535: static void import_append_char(ImportCtx *p, int c){ ! 14536: if( p->n+1>=p->nAlloc ){ ! 14537: p->nAlloc += p->nAlloc + 100; ! 14538: p->z = sqlite3_realloc64(p->z, p->nAlloc); ! 14539: if( p->z==0 ) shell_out_of_memory(); 1.2 misho 14540: } 1.5 ! misho 14541: p->z[p->n++] = (char)c; 1.2 misho 14542: } 14543: 1.5 ! misho 14544: /* Read a single field of CSV text. Compatible with rfc4180 and extended ! 14545: ** with the option of having a separator other than ",". 1.2 misho 14546: ** 1.5 ! misho 14547: ** + Input comes from p->in. ! 14548: ** + Store results in p->z of length p->n. Space to hold p->z comes ! 14549: ** from sqlite3_malloc64(). ! 14550: ** + Use p->cSep as the column separator. The default is ",". ! 14551: ** + Use p->rSep as the row separator. The default is "\n". ! 14552: ** + Keep track of the line number in p->nLine. ! 14553: ** + Store the character that terminates the field in p->cTerm. Store ! 14554: ** EOF on end-of-file. ! 14555: ** + Report syntax errors on stderr 1.2 misho 14556: */ 1.5 ! misho 14557: static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ ! 14558: int c; ! 14559: int cSep = p->cColSep; ! 14560: int rSep = p->cRowSep; ! 14561: p->n = 0; ! 14562: c = fgetc(p->in); ! 14563: if( c==EOF || seenInterrupt ){ ! 14564: p->cTerm = EOF; 1.2 misho 14565: return 0; 14566: } 1.5 ! misho 14567: if( c=='"' ){ ! 14568: int pc, ppc; ! 14569: int startLine = p->nLine; ! 14570: int cQuote = c; ! 14571: pc = ppc = 0; ! 14572: while( 1 ){ ! 14573: c = fgetc(p->in); ! 14574: if( c==rSep ) p->nLine++; ! 14575: if( c==cQuote ){ ! 14576: if( pc==cQuote ){ ! 14577: pc = 0; ! 14578: continue; ! 14579: } ! 14580: } ! 14581: if( (c==cSep && pc==cQuote) ! 14582: || (c==rSep && pc==cQuote) ! 14583: || (c==rSep && pc=='\r' && ppc==cQuote) ! 14584: || (c==EOF && pc==cQuote) ! 14585: ){ ! 14586: do{ p->n--; }while( p->z[p->n]!=cQuote ); ! 14587: p->cTerm = c; ! 14588: break; ! 14589: } ! 14590: if( pc==cQuote && c!='\r' ){ ! 14591: utf8_printf(stderr, "%s:%d: unescaped %c character\n", ! 14592: p->zFile, p->nLine, cQuote); ! 14593: } ! 14594: if( c==EOF ){ ! 14595: utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n", ! 14596: p->zFile, startLine, cQuote); ! 14597: p->cTerm = c; ! 14598: break; ! 14599: } ! 14600: import_append_char(p, c); ! 14601: ppc = pc; ! 14602: pc = c; 1.2 misho 14603: } 14604: }else{ 1.5 ! misho 14605: /* If this is the first field being parsed and it begins with the ! 14606: ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ ! 14607: if( (c&0xff)==0xef && p->bNotFirst==0 ){ ! 14608: import_append_char(p, c); ! 14609: c = fgetc(p->in); ! 14610: if( (c&0xff)==0xbb ){ ! 14611: import_append_char(p, c); ! 14612: c = fgetc(p->in); ! 14613: if( (c&0xff)==0xbf ){ ! 14614: p->bNotFirst = 1; ! 14615: p->n = 0; ! 14616: return csv_read_one_field(p); ! 14617: } ! 14618: } 1.2 misho 14619: } 1.5 ! misho 14620: while( c!=EOF && c!=cSep && c!=rSep ){ ! 14621: import_append_char(p, c); ! 14622: c = fgetc(p->in); 1.3 misho 14623: } 1.5 ! misho 14624: if( c==rSep ){ ! 14625: p->nLine++; ! 14626: if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; 1.4 misho 14627: } 1.5 ! misho 14628: p->cTerm = c; 1.2 misho 14629: } 1.5 ! misho 14630: if( p->z ) p->z[p->n] = 0; ! 14631: p->bNotFirst = 1; ! 14632: return p->z; 1.2 misho 14633: } 14634: 1.5 ! misho 14635: /* Read a single field of ASCII delimited text. ! 14636: ** ! 14637: ** + Input comes from p->in. ! 14638: ** + Store results in p->z of length p->n. Space to hold p->z comes ! 14639: ** from sqlite3_malloc64(). ! 14640: ** + Use p->cSep as the column separator. The default is "\x1F". ! 14641: ** + Use p->rSep as the row separator. The default is "\x1E". ! 14642: ** + Keep track of the row number in p->nLine. ! 14643: ** + Store the character that terminates the field in p->cTerm. Store ! 14644: ** EOF on end-of-file. ! 14645: ** + Report syntax errors on stderr 1.2 misho 14646: */ 1.5 ! misho 14647: static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ ! 14648: int c; ! 14649: int cSep = p->cColSep; ! 14650: int rSep = p->cRowSep; ! 14651: p->n = 0; ! 14652: c = fgetc(p->in); ! 14653: if( c==EOF || seenInterrupt ){ ! 14654: p->cTerm = EOF; ! 14655: return 0; ! 14656: } ! 14657: while( c!=EOF && c!=cSep && c!=rSep ){ ! 14658: import_append_char(p, c); ! 14659: c = fgetc(p->in); 1.2 misho 14660: } 1.5 ! misho 14661: if( c==rSep ){ ! 14662: p->nLine++; 1.4 misho 14663: } 1.5 ! misho 14664: p->cTerm = c; ! 14665: if( p->z ) p->z[p->n] = 0; ! 14666: return p->z; 1.4 misho 14667: } 14668: 1.2 misho 14669: /* 1.5 ! misho 14670: ** Try to transfer data for table zTable. If an error is seen while ! 14671: ** moving forward, try to go backwards. The backwards movement won't ! 14672: ** work for WITHOUT ROWID tables. 1.2 misho 14673: */ 1.5 ! misho 14674: static void tryToCloneData( ! 14675: ShellState *p, ! 14676: sqlite3 *newDb, ! 14677: const char *zTable 1.2 misho 14678: ){ 1.5 ! misho 14679: sqlite3_stmt *pQuery = 0; ! 14680: sqlite3_stmt *pInsert = 0; ! 14681: char *zQuery = 0; ! 14682: char *zInsert = 0; ! 14683: int rc; ! 14684: int i, j, n; ! 14685: int nTable = strlen30(zTable); ! 14686: int k = 0; ! 14687: int cnt = 0; ! 14688: const int spinRate = 10000; 1.2 misho 14689: 1.5 ! misho 14690: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); ! 14691: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); ! 14692: if( rc ){ ! 14693: utf8_printf(stderr, "Error %d: %s on [%s]\n", ! 14694: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), ! 14695: zQuery); ! 14696: goto end_data_xfer; ! 14697: } ! 14698: n = sqlite3_column_count(pQuery); ! 14699: zInsert = sqlite3_malloc64(200 + nTable + n*3); ! 14700: if( zInsert==0 ) shell_out_of_memory(); ! 14701: sqlite3_snprintf(200+nTable,zInsert, ! 14702: "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); ! 14703: i = strlen30(zInsert); ! 14704: for(j=1; j<n; j++){ ! 14705: memcpy(zInsert+i, ",?", 2); ! 14706: i += 2; ! 14707: } ! 14708: memcpy(zInsert+i, ");", 3); ! 14709: rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0); ! 14710: if( rc ){ ! 14711: utf8_printf(stderr, "Error %d: %s on [%s]\n", ! 14712: sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), ! 14713: zQuery); ! 14714: goto end_data_xfer; 1.2 misho 14715: } 1.5 ! misho 14716: for(k=0; k<2; k++){ ! 14717: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ ! 14718: for(i=0; i<n; i++){ ! 14719: switch( sqlite3_column_type(pQuery, i) ){ ! 14720: case SQLITE_NULL: { ! 14721: sqlite3_bind_null(pInsert, i+1); ! 14722: break; ! 14723: } ! 14724: case SQLITE_INTEGER: { ! 14725: sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i)); ! 14726: break; ! 14727: } ! 14728: case SQLITE_FLOAT: { ! 14729: sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i)); ! 14730: break; ! 14731: } ! 14732: case SQLITE_TEXT: { ! 14733: sqlite3_bind_text(pInsert, i+1, ! 14734: (const char*)sqlite3_column_text(pQuery,i), ! 14735: -1, SQLITE_STATIC); ! 14736: break; ! 14737: } ! 14738: case SQLITE_BLOB: { ! 14739: sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i), ! 14740: sqlite3_column_bytes(pQuery,i), ! 14741: SQLITE_STATIC); ! 14742: break; ! 14743: } ! 14744: } ! 14745: } /* End for */ ! 14746: rc = sqlite3_step(pInsert); ! 14747: if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ ! 14748: utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb), ! 14749: sqlite3_errmsg(newDb)); ! 14750: } ! 14751: sqlite3_reset(pInsert); ! 14752: cnt++; ! 14753: if( (cnt%spinRate)==0 ){ ! 14754: printf("%c\b", "|/-\\"[(cnt/spinRate)%4]); ! 14755: fflush(stdout); ! 14756: } ! 14757: } /* End while */ ! 14758: if( rc==SQLITE_DONE ) break; ! 14759: sqlite3_finalize(pQuery); ! 14760: sqlite3_free(zQuery); ! 14761: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;", ! 14762: zTable); ! 14763: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); ! 14764: if( rc ){ ! 14765: utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable); ! 14766: break; 1.4 misho 14767: } 1.5 ! misho 14768: } /* End for(k=0...) */ 1.2 misho 14769: 1.5 ! misho 14770: end_data_xfer: ! 14771: sqlite3_finalize(pQuery); ! 14772: sqlite3_finalize(pInsert); ! 14773: sqlite3_free(zQuery); ! 14774: sqlite3_free(zInsert); ! 14775: } 1.4 misho 14776: 1.2 misho 14777: 14778: /* 1.5 ! misho 14779: ** Try to transfer all rows of the schema that match zWhere. For ! 14780: ** each row, invoke xForEach() on the object defined by that row. ! 14781: ** If an error is encountered while moving forward through the ! 14782: ** sqlite_schema table, try again moving backwards. 1.2 misho 14783: */ 1.5 ! misho 14784: static void tryToCloneSchema( ! 14785: ShellState *p, ! 14786: sqlite3 *newDb, ! 14787: const char *zWhere, ! 14788: void (*xForEach)(ShellState*,sqlite3*,const char*) 1.2 misho 14789: ){ 1.5 ! misho 14790: sqlite3_stmt *pQuery = 0; ! 14791: char *zQuery = 0; ! 14792: int rc; ! 14793: const unsigned char *zName; ! 14794: const unsigned char *zSql; ! 14795: char *zErrMsg = 0; ! 14796: ! 14797: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" ! 14798: " WHERE %s", zWhere); ! 14799: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); ! 14800: if( rc ){ ! 14801: utf8_printf(stderr, "Error: (%d) %s on [%s]\n", ! 14802: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), ! 14803: zQuery); ! 14804: goto end_schema_xfer; ! 14805: } ! 14806: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ ! 14807: zName = sqlite3_column_text(pQuery, 0); ! 14808: zSql = sqlite3_column_text(pQuery, 1); ! 14809: printf("%s... ", zName); fflush(stdout); ! 14810: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); ! 14811: if( zErrMsg ){ ! 14812: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); ! 14813: sqlite3_free(zErrMsg); ! 14814: zErrMsg = 0; ! 14815: } ! 14816: if( xForEach ){ ! 14817: xForEach(p, newDb, (const char*)zName); ! 14818: } ! 14819: printf("done\n"); ! 14820: } ! 14821: if( rc!=SQLITE_DONE ){ ! 14822: sqlite3_finalize(pQuery); ! 14823: sqlite3_free(zQuery); ! 14824: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" ! 14825: " WHERE %s ORDER BY rowid DESC", zWhere); ! 14826: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); ! 14827: if( rc ){ ! 14828: utf8_printf(stderr, "Error: (%d) %s on [%s]\n", ! 14829: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), ! 14830: zQuery); ! 14831: goto end_schema_xfer; ! 14832: } ! 14833: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ ! 14834: zName = sqlite3_column_text(pQuery, 0); ! 14835: zSql = sqlite3_column_text(pQuery, 1); ! 14836: printf("%s... ", zName); fflush(stdout); ! 14837: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); ! 14838: if( zErrMsg ){ ! 14839: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); ! 14840: sqlite3_free(zErrMsg); ! 14841: zErrMsg = 0; 1.2 misho 14842: } 1.5 ! misho 14843: if( xForEach ){ ! 14844: xForEach(p, newDb, (const char*)zName); 1.2 misho 14845: } 1.5 ! misho 14846: printf("done\n"); 1.4 misho 14847: } 14848: } 1.5 ! misho 14849: end_schema_xfer: ! 14850: sqlite3_finalize(pQuery); ! 14851: sqlite3_free(zQuery); 1.4 misho 14852: } 1.2 misho 14853: 1.4 misho 14854: /* 1.5 ! misho 14855: ** Open a new database file named "zNewDb". Try to recover as much information ! 14856: ** as possible out of the main database (which might be corrupt) and write it ! 14857: ** into zNewDb. 1.4 misho 14858: */ 1.5 ! misho 14859: static void tryToClone(ShellState *p, const char *zNewDb){ ! 14860: int rc; ! 14861: sqlite3 *newDb = 0; ! 14862: if( access(zNewDb,0)==0 ){ ! 14863: utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb); 1.4 misho 14864: return; 14865: } 1.5 ! misho 14866: rc = sqlite3_open(zNewDb, &newDb); ! 14867: if( rc ){ ! 14868: utf8_printf(stderr, "Cannot create output database: %s\n", ! 14869: sqlite3_errmsg(newDb)); ! 14870: }else{ ! 14871: sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); ! 14872: sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); ! 14873: tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); ! 14874: tryToCloneSchema(p, newDb, "type!='table'", 0); ! 14875: sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); ! 14876: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); 1.4 misho 14877: } 1.5 ! misho 14878: close_db(newDb); 1.4 misho 14879: } 14880: 14881: /* 1.5 ! misho 14882: ** Change the output file back to stdout. ! 14883: ** ! 14884: ** If the p->doXdgOpen flag is set, that means the output was being ! 14885: ** redirected to a temporary file named by p->zTempFile. In that case, ! 14886: ** launch start/open/xdg-open on that temporary file. 1.4 misho 14887: */ 1.5 ! misho 14888: static void output_reset(ShellState *p){ ! 14889: if( p->outfile[0]=='|' ){ ! 14890: #ifndef SQLITE_OMIT_POPEN ! 14891: pclose(p->out); ! 14892: #endif ! 14893: }else{ ! 14894: output_file_close(p->out); ! 14895: #ifndef SQLITE_NOHAVE_SYSTEM ! 14896: if( p->doXdgOpen ){ ! 14897: const char *zXdgOpenCmd = ! 14898: #if defined(_WIN32) ! 14899: "start"; ! 14900: #elif defined(__APPLE__) ! 14901: "open"; ! 14902: #else ! 14903: "xdg-open"; ! 14904: #endif ! 14905: char *zCmd; ! 14906: zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); ! 14907: if( system(zCmd) ){ ! 14908: utf8_printf(stderr, "Failed: [%s]\n", zCmd); ! 14909: }else{ ! 14910: /* Give the start/open/xdg-open command some time to get ! 14911: ** going before we continue, and potential delete the ! 14912: ** p->zTempFile data file out from under it */ ! 14913: sqlite3_sleep(2000); ! 14914: } ! 14915: sqlite3_free(zCmd); ! 14916: outputModePop(p); ! 14917: p->doXdgOpen = 0; ! 14918: } ! 14919: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ ! 14920: } ! 14921: p->outfile[0] = 0; ! 14922: p->out = stdout; 1.4 misho 14923: } 14924: 14925: /* 1.5 ! misho 14926: ** Run an SQL command and return the single integer result. 1.4 misho 14927: */ 1.5 ! misho 14928: static int db_int(ShellState *p, const char *zSql){ ! 14929: sqlite3_stmt *pStmt; ! 14930: int res = 0; ! 14931: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 14932: if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ ! 14933: res = sqlite3_column_int(pStmt,0); ! 14934: } ! 14935: sqlite3_finalize(pStmt); ! 14936: return res; 1.4 misho 14937: } 14938: 14939: /* 1.5 ! misho 14940: ** Convert a 2-byte or 4-byte big-endian integer into a native integer 1.4 misho 14941: */ 1.5 ! misho 14942: static unsigned int get2byteInt(unsigned char *a){ ! 14943: return (a[0]<<8) + a[1]; ! 14944: } ! 14945: static unsigned int get4byteInt(unsigned char *a){ ! 14946: return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; 1.4 misho 14947: } 14948: 14949: /* 1.5 ! misho 14950: ** Implementation of the ".dbinfo" command. 1.4 misho 14951: ** 1.5 ! misho 14952: ** Return 1 on error, 2 to exit, and 0 otherwise. 1.4 misho 14953: */ 1.5 ! misho 14954: static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ ! 14955: static const struct { const char *zName; int ofst; } aField[] = { ! 14956: { "file change counter:", 24 }, ! 14957: { "database page count:", 28 }, ! 14958: { "freelist page count:", 36 }, ! 14959: { "schema cookie:", 40 }, ! 14960: { "schema format:", 44 }, ! 14961: { "default cache size:", 48 }, ! 14962: { "autovacuum top root:", 52 }, ! 14963: { "incremental vacuum:", 64 }, ! 14964: { "text encoding:", 56 }, ! 14965: { "user version:", 60 }, ! 14966: { "application id:", 68 }, ! 14967: { "software version:", 96 }, ! 14968: }; ! 14969: static const struct { const char *zName; const char *zSql; } aQuery[] = { ! 14970: { "number of tables:", ! 14971: "SELECT count(*) FROM %s WHERE type='table'" }, ! 14972: { "number of indexes:", ! 14973: "SELECT count(*) FROM %s WHERE type='index'" }, ! 14974: { "number of triggers:", ! 14975: "SELECT count(*) FROM %s WHERE type='trigger'" }, ! 14976: { "number of views:", ! 14977: "SELECT count(*) FROM %s WHERE type='view'" }, ! 14978: { "schema size:", ! 14979: "SELECT total(length(sql)) FROM %s" }, ! 14980: }; ! 14981: int i, rc; ! 14982: unsigned iDataVersion; ! 14983: char *zSchemaTab; ! 14984: char *zDb = nArg>=2 ? azArg[1] : "main"; ! 14985: sqlite3_stmt *pStmt = 0; ! 14986: unsigned char aHdr[100]; ! 14987: open_db(p, 0); ! 14988: if( p->db==0 ) return 1; ! 14989: rc = sqlite3_prepare_v2(p->db, ! 14990: "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", ! 14991: -1, &pStmt, 0); ! 14992: if( rc ){ ! 14993: utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db)); ! 14994: sqlite3_finalize(pStmt); ! 14995: return 1; ! 14996: } ! 14997: sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); ! 14998: if( sqlite3_step(pStmt)==SQLITE_ROW ! 14999: && sqlite3_column_bytes(pStmt,0)>100 ! 15000: ){ ! 15001: memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100); ! 15002: sqlite3_finalize(pStmt); ! 15003: }else{ ! 15004: raw_printf(stderr, "unable to read database header\n"); ! 15005: sqlite3_finalize(pStmt); ! 15006: return 1; 1.4 misho 15007: } 1.5 ! misho 15008: i = get2byteInt(aHdr+16); ! 15009: if( i==1 ) i = 65536; ! 15010: utf8_printf(p->out, "%-20s %d\n", "database page size:", i); ! 15011: utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); ! 15012: utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); ! 15013: utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); ! 15014: for(i=0; i<ArraySize(aField); i++){ ! 15015: int ofst = aField[i].ofst; ! 15016: unsigned int val = get4byteInt(aHdr + ofst); ! 15017: utf8_printf(p->out, "%-20s %u", aField[i].zName, val); ! 15018: switch( ofst ){ ! 15019: case 56: { ! 15020: if( val==1 ) raw_printf(p->out, " (utf8)"); ! 15021: if( val==2 ) raw_printf(p->out, " (utf16le)"); ! 15022: if( val==3 ) raw_printf(p->out, " (utf16be)"); 1.2 misho 15023: } 15024: } 1.5 ! misho 15025: raw_printf(p->out, "\n"); ! 15026: } ! 15027: if( zDb==0 ){ ! 15028: zSchemaTab = sqlite3_mprintf("main.sqlite_schema"); ! 15029: }else if( strcmp(zDb,"temp")==0 ){ ! 15030: zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema"); ! 15031: }else{ ! 15032: zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb); ! 15033: } ! 15034: for(i=0; i<ArraySize(aQuery); i++){ ! 15035: char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab); ! 15036: int val = db_int(p, zSql); ! 15037: sqlite3_free(zSql); ! 15038: utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); ! 15039: } ! 15040: sqlite3_free(zSchemaTab); ! 15041: sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); ! 15042: utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); ! 15043: return 0; 1.2 misho 15044: } 15045: 15046: /* 1.5 ! misho 15047: ** Print the current sqlite3_errmsg() value to stderr and return 1. 1.2 misho 15048: */ 1.5 ! misho 15049: static int shellDatabaseError(sqlite3 *db){ ! 15050: const char *zErr = sqlite3_errmsg(db); ! 15051: utf8_printf(stderr, "Error: %s\n", zErr); ! 15052: return 1; 1.2 misho 15053: } 15054: 15055: /* 1.5 ! misho 15056: ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE ! 15057: ** if they match and FALSE (0) if they do not match. ! 15058: ** ! 15059: ** Globbing rules: ! 15060: ** ! 15061: ** '*' Matches any sequence of zero or more characters. ! 15062: ** ! 15063: ** '?' Matches exactly one character. ! 15064: ** ! 15065: ** [...] Matches one character from the enclosed list of ! 15066: ** characters. ! 15067: ** ! 15068: ** [^...] Matches one character not in the enclosed list. ! 15069: ** ! 15070: ** '#' Matches any sequence of one or more digits with an ! 15071: ** optional + or - sign in front ! 15072: ** ! 15073: ** ' ' Any span of whitespace matches any other span of ! 15074: ** whitespace. 1.2 misho 15075: ** 1.5 ! misho 15076: ** Extra whitespace at the end of z[] is ignored. 1.2 misho 15077: */ 1.5 ! misho 15078: static int testcase_glob(const char *zGlob, const char *z){ ! 15079: int c, c2; ! 15080: int invert; ! 15081: int seen; ! 15082: ! 15083: while( (c = (*(zGlob++)))!=0 ){ ! 15084: if( IsSpace(c) ){ ! 15085: if( !IsSpace(*z) ) return 0; ! 15086: while( IsSpace(*zGlob) ) zGlob++; ! 15087: while( IsSpace(*z) ) z++; ! 15088: }else if( c=='*' ){ ! 15089: while( (c=(*(zGlob++))) == '*' || c=='?' ){ ! 15090: if( c=='?' && (*(z++))==0 ) return 0; ! 15091: } ! 15092: if( c==0 ){ ! 15093: return 1; ! 15094: }else if( c=='[' ){ ! 15095: while( *z && testcase_glob(zGlob-1,z)==0 ){ ! 15096: z++; ! 15097: } ! 15098: return (*z)!=0; ! 15099: } ! 15100: while( (c2 = (*(z++)))!=0 ){ ! 15101: while( c2!=c ){ ! 15102: c2 = *(z++); ! 15103: if( c2==0 ) return 0; ! 15104: } ! 15105: if( testcase_glob(zGlob,z) ) return 1; ! 15106: } ! 15107: return 0; ! 15108: }else if( c=='?' ){ ! 15109: if( (*(z++))==0 ) return 0; ! 15110: }else if( c=='[' ){ ! 15111: int prior_c = 0; ! 15112: seen = 0; ! 15113: invert = 0; ! 15114: c = *(z++); ! 15115: if( c==0 ) return 0; ! 15116: c2 = *(zGlob++); ! 15117: if( c2=='^' ){ ! 15118: invert = 1; ! 15119: c2 = *(zGlob++); ! 15120: } ! 15121: if( c2==']' ){ ! 15122: if( c==']' ) seen = 1; ! 15123: c2 = *(zGlob++); ! 15124: } ! 15125: while( c2 && c2!=']' ){ ! 15126: if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ ! 15127: c2 = *(zGlob++); ! 15128: if( c>=prior_c && c<=c2 ) seen = 1; ! 15129: prior_c = 0; ! 15130: }else{ ! 15131: if( c==c2 ){ ! 15132: seen = 1; ! 15133: } ! 15134: prior_c = c2; ! 15135: } ! 15136: c2 = *(zGlob++); ! 15137: } ! 15138: if( c2==0 || (seen ^ invert)==0 ) return 0; ! 15139: }else if( c=='#' ){ ! 15140: if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++; ! 15141: if( !IsDigit(z[0]) ) return 0; ! 15142: z++; ! 15143: while( IsDigit(z[0]) ){ z++; } 1.2 misho 15144: }else{ 1.5 ! misho 15145: if( c!=(*(z++)) ) return 0; 1.2 misho 15146: } 15147: } 1.5 ! misho 15148: while( IsSpace(*z) ){ z++; } ! 15149: return *z==0; 1.2 misho 15150: } 15151: 1.5 ! misho 15152: 1.2 misho 15153: /* 1.5 ! misho 15154: ** Compare the string as a command-line option with either one or two ! 15155: ** initial "-" characters. 1.2 misho 15156: */ 1.5 ! misho 15157: static int optionMatch(const char *zStr, const char *zOpt){ ! 15158: if( zStr[0]!='-' ) return 0; ! 15159: zStr++; ! 15160: if( zStr[0]=='-' ) zStr++; ! 15161: return strcmp(zStr, zOpt)==0; ! 15162: } 1.2 misho 15163: 1.4 misho 15164: /* 1.5 ! misho 15165: ** Delete a file. 1.4 misho 15166: */ 1.5 ! misho 15167: int shellDeleteFile(const char *zFilename){ ! 15168: int rc; ! 15169: #ifdef _WIN32 ! 15170: wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename); ! 15171: rc = _wunlink(z); ! 15172: sqlite3_free(z); ! 15173: #else ! 15174: rc = unlink(zFilename); ! 15175: #endif ! 15176: return rc; 1.4 misho 15177: } 15178: 15179: /* 1.5 ! misho 15180: ** Try to delete the temporary file (if there is one) and free the ! 15181: ** memory used to hold the name of the temp file. 1.4 misho 15182: */ 1.5 ! misho 15183: static void clearTempFile(ShellState *p){ ! 15184: if( p->zTempFile==0 ) return; ! 15185: if( p->doXdgOpen ) return; ! 15186: if( shellDeleteFile(p->zTempFile) ) return; ! 15187: sqlite3_free(p->zTempFile); ! 15188: p->zTempFile = 0; ! 15189: } 1.4 misho 15190: 1.5 ! misho 15191: /* ! 15192: ** Create a new temp file name with the given suffix. ! 15193: */ ! 15194: static void newTempFile(ShellState *p, const char *zSuffix){ ! 15195: clearTempFile(p); ! 15196: sqlite3_free(p->zTempFile); ! 15197: p->zTempFile = 0; ! 15198: if( p->db ){ ! 15199: sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); ! 15200: } ! 15201: if( p->zTempFile==0 ){ ! 15202: /* If p->db is an in-memory database then the TEMPFILENAME file-control ! 15203: ** will not work and we will need to fallback to guessing */ ! 15204: char *zTemp; ! 15205: sqlite3_uint64 r; ! 15206: sqlite3_randomness(sizeof(r), &r); ! 15207: zTemp = getenv("TEMP"); ! 15208: if( zTemp==0 ) zTemp = getenv("TMP"); ! 15209: if( zTemp==0 ){ ! 15210: #ifdef _WIN32 ! 15211: zTemp = "\\tmp"; ! 15212: #else ! 15213: zTemp = "/tmp"; ! 15214: #endif ! 15215: } ! 15216: p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix); 1.4 misho 15217: }else{ 1.5 ! misho 15218: p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); ! 15219: } ! 15220: if( p->zTempFile==0 ){ ! 15221: raw_printf(stderr, "out of memory\n"); ! 15222: exit(1); 1.4 misho 15223: } 15224: } 15225: 1.5 ! misho 15226: 1.4 misho 15227: /* 1.5 ! misho 15228: ** The implementation of SQL scalar function fkey_collate_clause(), used ! 15229: ** by the ".lint fkey-indexes" command. This scalar function is always ! 15230: ** called with four arguments - the parent table name, the parent column name, ! 15231: ** the child table name and the child column name. ! 15232: ** ! 15233: ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col') ! 15234: ** ! 15235: ** If either of the named tables or columns do not exist, this function ! 15236: ** returns an empty string. An empty string is also returned if both tables ! 15237: ** and columns exist but have the same default collation sequence. Or, ! 15238: ** if both exist but the default collation sequences are different, this ! 15239: ** function returns the string " COLLATE <parent-collation>", where ! 15240: ** <parent-collation> is the default collation sequence of the parent column. ! 15241: */ ! 15242: static void shellFkeyCollateClause( ! 15243: sqlite3_context *pCtx, ! 15244: int nVal, ! 15245: sqlite3_value **apVal 1.4 misho 15246: ){ 1.5 ! misho 15247: sqlite3 *db = sqlite3_context_db_handle(pCtx); ! 15248: const char *zParent; ! 15249: const char *zParentCol; ! 15250: const char *zParentSeq; ! 15251: const char *zChild; ! 15252: const char *zChildCol; ! 15253: const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ ! 15254: int rc; ! 15255: ! 15256: assert( nVal==4 ); ! 15257: zParent = (const char*)sqlite3_value_text(apVal[0]); ! 15258: zParentCol = (const char*)sqlite3_value_text(apVal[1]); ! 15259: zChild = (const char*)sqlite3_value_text(apVal[2]); ! 15260: zChildCol = (const char*)sqlite3_value_text(apVal[3]); ! 15261: ! 15262: sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); ! 15263: rc = sqlite3_table_column_metadata( ! 15264: db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0 ! 15265: ); ! 15266: if( rc==SQLITE_OK ){ ! 15267: rc = sqlite3_table_column_metadata( ! 15268: db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0 ! 15269: ); ! 15270: } 1.4 misho 15271: 1.5 ! misho 15272: if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){ ! 15273: char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq); ! 15274: sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); ! 15275: sqlite3_free(z); 1.4 misho 15276: } 15277: } 15278: 1.5 ! misho 15279: 1.4 misho 15280: /* 1.5 ! misho 15281: ** The implementation of dot-command ".lint fkey-indexes". 1.4 misho 15282: */ 1.5 ! misho 15283: static int lintFkeyIndexes( ! 15284: ShellState *pState, /* Current shell tool state */ ! 15285: char **azArg, /* Array of arguments passed to dot command */ ! 15286: int nArg /* Number of entries in azArg[] */ ! 15287: ){ ! 15288: sqlite3 *db = pState->db; /* Database handle to query "main" db of */ ! 15289: FILE *out = pState->out; /* Stream to write non-error output to */ ! 15290: int bVerbose = 0; /* If -verbose is present */ ! 15291: int bGroupByParent = 0; /* If -groupbyparent is present */ ! 15292: int i; /* To iterate through azArg[] */ ! 15293: const char *zIndent = ""; /* How much to indent CREATE INDEX by */ ! 15294: int rc; /* Return code */ ! 15295: sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */ ! 15296: ! 15297: /* ! 15298: ** This SELECT statement returns one row for each foreign key constraint ! 15299: ** in the schema of the main database. The column values are: ! 15300: ** ! 15301: ** 0. The text of an SQL statement similar to: ! 15302: ** ! 15303: ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?" ! 15304: ** ! 15305: ** This SELECT is similar to the one that the foreign keys implementation ! 15306: ** needs to run internally on child tables. If there is an index that can ! 15307: ** be used to optimize this query, then it can also be used by the FK ! 15308: ** implementation to optimize DELETE or UPDATE statements on the parent ! 15309: ** table. ! 15310: ** ! 15311: ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by ! 15312: ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema ! 15313: ** contains an index that can be used to optimize the query. ! 15314: ** ! 15315: ** 2. Human readable text that describes the child table and columns. e.g. ! 15316: ** ! 15317: ** "child_table(child_key1, child_key2)" ! 15318: ** ! 15319: ** 3. Human readable text that describes the parent table and columns. e.g. ! 15320: ** ! 15321: ** "parent_table(parent_key1, parent_key2)" ! 15322: ** ! 15323: ** 4. A full CREATE INDEX statement for an index that could be used to ! 15324: ** optimize DELETE or UPDATE statements on the parent table. e.g. ! 15325: ** ! 15326: ** "CREATE INDEX child_table_child_key ON child_table(child_key)" ! 15327: ** ! 15328: ** 5. The name of the parent table. ! 15329: ** ! 15330: ** These six values are used by the C logic below to generate the report. ! 15331: */ ! 15332: const char *zSql = ! 15333: "SELECT " ! 15334: " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '" ! 15335: " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " ! 15336: " || fkey_collate_clause(" ! 15337: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" ! 15338: ", " ! 15339: " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('" ! 15340: " || group_concat('*=?', ' AND ') || ')'" ! 15341: ", " ! 15342: " s.name || '(' || group_concat(f.[from], ', ') || ')'" ! 15343: ", " ! 15344: " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'" ! 15345: ", " ! 15346: " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))" ! 15347: " || ' ON ' || quote(s.name) || '('" ! 15348: " || group_concat(quote(f.[from]) ||" ! 15349: " fkey_collate_clause(" ! 15350: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')" ! 15351: " || ');'" ! 15352: ", " ! 15353: " f.[table] " ! 15354: "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f " ! 15355: "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) " ! 15356: "GROUP BY s.name, f.id " ! 15357: "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)" ! 15358: ; ! 15359: const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)"; ! 15360: ! 15361: for(i=2; i<nArg; i++){ ! 15362: int n = strlen30(azArg[i]); ! 15363: if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){ ! 15364: bVerbose = 1; ! 15365: } ! 15366: else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){ ! 15367: bGroupByParent = 1; ! 15368: zIndent = " "; ! 15369: } ! 15370: else{ ! 15371: raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", ! 15372: azArg[0], azArg[1] ! 15373: ); ! 15374: return SQLITE_ERROR; ! 15375: } ! 15376: } ! 15377: ! 15378: /* Register the fkey_collate_clause() SQL function */ ! 15379: rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, ! 15380: 0, shellFkeyCollateClause, 0, 0 ! 15381: ); ! 15382: ! 15383: ! 15384: if( rc==SQLITE_OK ){ ! 15385: rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0); ! 15386: } ! 15387: if( rc==SQLITE_OK ){ ! 15388: sqlite3_bind_int(pSql, 1, bGroupByParent); 1.4 misho 15389: } 15390: 1.5 ! misho 15391: if( rc==SQLITE_OK ){ ! 15392: int rc2; ! 15393: char *zPrev = 0; ! 15394: while( SQLITE_ROW==sqlite3_step(pSql) ){ ! 15395: int res = -1; ! 15396: sqlite3_stmt *pExplain = 0; ! 15397: const char *zEQP = (const char*)sqlite3_column_text(pSql, 0); ! 15398: const char *zGlob = (const char*)sqlite3_column_text(pSql, 1); ! 15399: const char *zFrom = (const char*)sqlite3_column_text(pSql, 2); ! 15400: const char *zTarget = (const char*)sqlite3_column_text(pSql, 3); ! 15401: const char *zCI = (const char*)sqlite3_column_text(pSql, 4); ! 15402: const char *zParent = (const char*)sqlite3_column_text(pSql, 5); ! 15403: ! 15404: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); ! 15405: if( rc!=SQLITE_OK ) break; ! 15406: if( SQLITE_ROW==sqlite3_step(pExplain) ){ ! 15407: const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3); ! 15408: res = ( ! 15409: 0==sqlite3_strglob(zGlob, zPlan) ! 15410: || 0==sqlite3_strglob(zGlobIPK, zPlan) ! 15411: ); ! 15412: } ! 15413: rc = sqlite3_finalize(pExplain); ! 15414: if( rc!=SQLITE_OK ) break; ! 15415: ! 15416: if( res<0 ){ ! 15417: raw_printf(stderr, "Error: internal error"); ! 15418: break; ! 15419: }else{ ! 15420: if( bGroupByParent ! 15421: && (bVerbose || res==0) ! 15422: && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) ! 15423: ){ ! 15424: raw_printf(out, "-- Parent table %s\n", zParent); ! 15425: sqlite3_free(zPrev); ! 15426: zPrev = sqlite3_mprintf("%s", zParent); ! 15427: } ! 15428: ! 15429: if( res==0 ){ ! 15430: raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); ! 15431: }else if( bVerbose ){ ! 15432: raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", ! 15433: zIndent, zFrom, zTarget ! 15434: ); ! 15435: } ! 15436: } ! 15437: } ! 15438: sqlite3_free(zPrev); ! 15439: ! 15440: if( rc!=SQLITE_OK ){ ! 15441: raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); ! 15442: } ! 15443: ! 15444: rc2 = sqlite3_finalize(pSql); ! 15445: if( rc==SQLITE_OK && rc2!=SQLITE_OK ){ ! 15446: rc = rc2; ! 15447: raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); ! 15448: } ! 15449: }else{ ! 15450: raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); 1.4 misho 15451: } 1.5 ! misho 15452: ! 15453: return rc; 1.4 misho 15454: } 15455: 15456: /* 1.5 ! misho 15457: ** Implementation of ".lint" dot command. 1.4 misho 15458: */ 1.5 ! misho 15459: static int lintDotCommand( ! 15460: ShellState *pState, /* Current shell tool state */ ! 15461: char **azArg, /* Array of arguments passed to dot command */ ! 15462: int nArg /* Number of entries in azArg[] */ ! 15463: ){ ! 15464: int n; ! 15465: n = (nArg>=2 ? strlen30(azArg[1]) : 0); ! 15466: if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; ! 15467: return lintFkeyIndexes(pState, azArg, nArg); ! 15468: ! 15469: usage: ! 15470: raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]); ! 15471: raw_printf(stderr, "Where sub-commands are:\n"); ! 15472: raw_printf(stderr, " fkey-indexes\n"); ! 15473: return SQLITE_ERROR; ! 15474: } ! 15475: ! 15476: #if !defined SQLITE_OMIT_VIRTUALTABLE ! 15477: static void shellPrepare( ! 15478: sqlite3 *db, ! 15479: int *pRc, ! 15480: const char *zSql, ! 15481: sqlite3_stmt **ppStmt ! 15482: ){ ! 15483: *ppStmt = 0; ! 15484: if( *pRc==SQLITE_OK ){ ! 15485: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); ! 15486: if( rc!=SQLITE_OK ){ ! 15487: raw_printf(stderr, "sql error: %s (%d)\n", ! 15488: sqlite3_errmsg(db), sqlite3_errcode(db) ! 15489: ); ! 15490: *pRc = rc; ! 15491: } 1.4 misho 15492: } 15493: } 1.2 misho 15494: 15495: /* 1.5 ! misho 15496: ** Create a prepared statement using printf-style arguments for the SQL. ! 15497: ** ! 15498: ** This routine is could be marked "static". But it is not always used, ! 15499: ** depending on compile-time options. By omitting the "static", we avoid ! 15500: ** nuisance compiler warnings about "defined but not used". ! 15501: */ ! 15502: void shellPreparePrintf( ! 15503: sqlite3 *db, ! 15504: int *pRc, ! 15505: sqlite3_stmt **ppStmt, ! 15506: const char *zFmt, ! 15507: ... ! 15508: ){ ! 15509: *ppStmt = 0; ! 15510: if( *pRc==SQLITE_OK ){ ! 15511: va_list ap; ! 15512: char *z; ! 15513: va_start(ap, zFmt); ! 15514: z = sqlite3_vmprintf(zFmt, ap); ! 15515: va_end(ap); ! 15516: if( z==0 ){ ! 15517: *pRc = SQLITE_NOMEM; ! 15518: }else{ ! 15519: shellPrepare(db, pRc, z, ppStmt); ! 15520: sqlite3_free(z); 1.2 misho 15521: } 1.5 ! misho 15522: } ! 15523: } ! 15524: ! 15525: /* Finalize the prepared statement created using shellPreparePrintf(). ! 15526: ** ! 15527: ** This routine is could be marked "static". But it is not always used, ! 15528: ** depending on compile-time options. By omitting the "static", we avoid ! 15529: ** nuisance compiler warnings about "defined but not used". ! 15530: */ ! 15531: void shellFinalize( ! 15532: int *pRc, ! 15533: sqlite3_stmt *pStmt ! 15534: ){ ! 15535: if( pStmt ){ ! 15536: sqlite3 *db = sqlite3_db_handle(pStmt); ! 15537: int rc = sqlite3_finalize(pStmt); ! 15538: if( *pRc==SQLITE_OK ){ ! 15539: if( rc!=SQLITE_OK ){ ! 15540: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); ! 15541: } ! 15542: *pRc = rc; 1.2 misho 15543: } 15544: } 15545: } 15546: 1.5 ! misho 15547: /* Reset the prepared statement created using shellPreparePrintf(). 1.2 misho 15548: ** 1.5 ! misho 15549: ** This routine is could be marked "static". But it is not always used, ! 15550: ** depending on compile-time options. By omitting the "static", we avoid ! 15551: ** nuisance compiler warnings about "defined but not used". ! 15552: */ ! 15553: void shellReset( ! 15554: int *pRc, ! 15555: sqlite3_stmt *pStmt ! 15556: ){ ! 15557: int rc = sqlite3_reset(pStmt); ! 15558: if( *pRc==SQLITE_OK ){ ! 15559: if( rc!=SQLITE_OK ){ ! 15560: sqlite3 *db = sqlite3_db_handle(pStmt); ! 15561: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); 1.2 misho 15562: } 1.5 ! misho 15563: *pRc = rc; 1.2 misho 15564: } 1.4 misho 15565: } 1.5 ! misho 15566: #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ ! 15567: ! 15568: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ! 15569: /****************************************************************************** ! 15570: ** The ".archive" or ".ar" command. ! 15571: */ ! 15572: /* ! 15573: ** Structure representing a single ".ar" command. ! 15574: */ ! 15575: typedef struct ArCommand ArCommand; ! 15576: struct ArCommand { ! 15577: u8 eCmd; /* An AR_CMD_* value */ ! 15578: u8 bVerbose; /* True if --verbose */ ! 15579: u8 bZip; /* True if the archive is a ZIP */ ! 15580: u8 bDryRun; /* True if --dry-run */ ! 15581: u8 bAppend; /* True if --append */ ! 15582: u8 fromCmdLine; /* Run from -A instead of .archive */ ! 15583: int nArg; /* Number of command arguments */ ! 15584: char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ ! 15585: const char *zFile; /* --file argument, or NULL */ ! 15586: const char *zDir; /* --directory argument, or NULL */ ! 15587: char **azArg; /* Array of command arguments */ ! 15588: ShellState *p; /* Shell state */ ! 15589: sqlite3 *db; /* Database containing the archive */ ! 15590: }; 1.4 misho 15591: 15592: /* 1.5 ! misho 15593: ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. 1.4 misho 15594: */ 1.5 ! misho 15595: static int arUsage(FILE *f){ ! 15596: showHelp(f,"archive"); ! 15597: return SQLITE_ERROR; 1.4 misho 15598: } 15599: 15600: /* 1.5 ! misho 15601: ** Print an error message for the .ar command to stderr and return ! 15602: ** SQLITE_ERROR. 1.4 misho 15603: */ 1.5 ! misho 15604: static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ ! 15605: va_list ap; ! 15606: char *z; ! 15607: va_start(ap, zFmt); ! 15608: z = sqlite3_vmprintf(zFmt, ap); ! 15609: va_end(ap); ! 15610: utf8_printf(stderr, "Error: %s\n", z); ! 15611: if( pAr->fromCmdLine ){ ! 15612: utf8_printf(stderr, "Use \"-A\" for more help\n"); 1.4 misho 15613: }else{ 1.5 ! misho 15614: utf8_printf(stderr, "Use \".archive --help\" for more help\n"); 1.4 misho 15615: } 1.5 ! misho 15616: sqlite3_free(z); ! 15617: return SQLITE_ERROR; ! 15618: } ! 15619: ! 15620: /* ! 15621: ** Values for ArCommand.eCmd. ! 15622: */ ! 15623: #define AR_CMD_CREATE 1 ! 15624: #define AR_CMD_UPDATE 2 ! 15625: #define AR_CMD_INSERT 3 ! 15626: #define AR_CMD_EXTRACT 4 ! 15627: #define AR_CMD_LIST 5 ! 15628: #define AR_CMD_HELP 6 ! 15629: ! 15630: /* ! 15631: ** Other (non-command) switches. ! 15632: */ ! 15633: #define AR_SWITCH_VERBOSE 7 ! 15634: #define AR_SWITCH_FILE 8 ! 15635: #define AR_SWITCH_DIRECTORY 9 ! 15636: #define AR_SWITCH_APPEND 10 ! 15637: #define AR_SWITCH_DRYRUN 11 ! 15638: ! 15639: static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ ! 15640: switch( eSwitch ){ ! 15641: case AR_CMD_CREATE: ! 15642: case AR_CMD_EXTRACT: ! 15643: case AR_CMD_LIST: ! 15644: case AR_CMD_UPDATE: ! 15645: case AR_CMD_INSERT: ! 15646: case AR_CMD_HELP: ! 15647: if( pAr->eCmd ){ ! 15648: return arErrorMsg(pAr, "multiple command options"); ! 15649: } ! 15650: pAr->eCmd = eSwitch; ! 15651: break; ! 15652: ! 15653: case AR_SWITCH_DRYRUN: ! 15654: pAr->bDryRun = 1; ! 15655: break; ! 15656: case AR_SWITCH_VERBOSE: ! 15657: pAr->bVerbose = 1; ! 15658: break; ! 15659: case AR_SWITCH_APPEND: ! 15660: pAr->bAppend = 1; ! 15661: /* Fall thru into --file */ ! 15662: case AR_SWITCH_FILE: ! 15663: pAr->zFile = zArg; ! 15664: break; ! 15665: case AR_SWITCH_DIRECTORY: ! 15666: pAr->zDir = zArg; 1.4 misho 15667: break; 15668: } 1.5 ! misho 15669: ! 15670: return SQLITE_OK; 1.2 misho 15671: } 15672: 15673: /* 1.5 ! misho 15674: ** Parse the command line for an ".ar" command. The results are written into ! 15675: ** structure (*pAr). SQLITE_OK is returned if the command line is parsed ! 15676: ** successfully, otherwise an error message is written to stderr and ! 15677: ** SQLITE_ERROR returned. ! 15678: */ ! 15679: static int arParseCommand( ! 15680: char **azArg, /* Array of arguments passed to dot command */ ! 15681: int nArg, /* Number of entries in azArg[] */ ! 15682: ArCommand *pAr /* Populate this object */ ! 15683: ){ ! 15684: struct ArSwitch { ! 15685: const char *zLong; ! 15686: char cShort; ! 15687: u8 eSwitch; ! 15688: u8 bArg; ! 15689: } aSwitch[] = { ! 15690: { "create", 'c', AR_CMD_CREATE, 0 }, ! 15691: { "extract", 'x', AR_CMD_EXTRACT, 0 }, ! 15692: { "insert", 'i', AR_CMD_INSERT, 0 }, ! 15693: { "list", 't', AR_CMD_LIST, 0 }, ! 15694: { "update", 'u', AR_CMD_UPDATE, 0 }, ! 15695: { "help", 'h', AR_CMD_HELP, 0 }, ! 15696: { "verbose", 'v', AR_SWITCH_VERBOSE, 0 }, ! 15697: { "file", 'f', AR_SWITCH_FILE, 1 }, ! 15698: { "append", 'a', AR_SWITCH_APPEND, 1 }, ! 15699: { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, ! 15700: { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, ! 15701: }; ! 15702: int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); ! 15703: struct ArSwitch *pEnd = &aSwitch[nSwitch]; ! 15704: ! 15705: if( nArg<=1 ){ ! 15706: utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); ! 15707: return arUsage(stderr); 1.4 misho 15708: }else{ 1.5 ! misho 15709: char *z = azArg[1]; ! 15710: if( z[0]!='-' ){ ! 15711: /* Traditional style [tar] invocation */ ! 15712: int i; ! 15713: int iArg = 2; ! 15714: for(i=0; z[i]; i++){ ! 15715: const char *zArg = 0; ! 15716: struct ArSwitch *pOpt; ! 15717: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ! 15718: if( z[i]==pOpt->cShort ) break; ! 15719: } ! 15720: if( pOpt==pEnd ){ ! 15721: return arErrorMsg(pAr, "unrecognized option: %c", z[i]); ! 15722: } ! 15723: if( pOpt->bArg ){ ! 15724: if( iArg>=nArg ){ ! 15725: return arErrorMsg(pAr, "option requires an argument: %c",z[i]); ! 15726: } ! 15727: zArg = azArg[iArg++]; ! 15728: } ! 15729: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; ! 15730: } ! 15731: pAr->nArg = nArg-iArg; ! 15732: if( pAr->nArg>0 ){ ! 15733: pAr->azArg = &azArg[iArg]; ! 15734: } ! 15735: }else{ ! 15736: /* Non-traditional invocation */ ! 15737: int iArg; ! 15738: for(iArg=1; iArg<nArg; iArg++){ ! 15739: int n; ! 15740: z = azArg[iArg]; ! 15741: if( z[0]!='-' ){ ! 15742: /* All remaining command line words are command arguments. */ ! 15743: pAr->azArg = &azArg[iArg]; ! 15744: pAr->nArg = nArg-iArg; ! 15745: break; ! 15746: } ! 15747: n = strlen30(z); ! 15748: ! 15749: if( z[1]!='-' ){ ! 15750: int i; ! 15751: /* One or more short options */ ! 15752: for(i=1; i<n; i++){ ! 15753: const char *zArg = 0; ! 15754: struct ArSwitch *pOpt; ! 15755: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ! 15756: if( z[i]==pOpt->cShort ) break; ! 15757: } ! 15758: if( pOpt==pEnd ){ ! 15759: return arErrorMsg(pAr, "unrecognized option: %c", z[i]); ! 15760: } ! 15761: if( pOpt->bArg ){ ! 15762: if( i<(n-1) ){ ! 15763: zArg = &z[i+1]; ! 15764: i = n; ! 15765: }else{ ! 15766: if( iArg>=(nArg-1) ){ ! 15767: return arErrorMsg(pAr, "option requires an argument: %c", ! 15768: z[i]); ! 15769: } ! 15770: zArg = azArg[++iArg]; ! 15771: } ! 15772: } ! 15773: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; ! 15774: } ! 15775: }else if( z[2]=='\0' ){ ! 15776: /* A -- option, indicating that all remaining command line words ! 15777: ** are command arguments. */ ! 15778: pAr->azArg = &azArg[iArg+1]; ! 15779: pAr->nArg = nArg-iArg-1; ! 15780: break; ! 15781: }else{ ! 15782: /* A long option */ ! 15783: const char *zArg = 0; /* Argument for option, if any */ ! 15784: struct ArSwitch *pMatch = 0; /* Matching option */ ! 15785: struct ArSwitch *pOpt; /* Iterator */ ! 15786: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ! 15787: const char *zLong = pOpt->zLong; ! 15788: if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){ ! 15789: if( pMatch ){ ! 15790: return arErrorMsg(pAr, "ambiguous option: %s",z); ! 15791: }else{ ! 15792: pMatch = pOpt; ! 15793: } ! 15794: } ! 15795: } ! 15796: ! 15797: if( pMatch==0 ){ ! 15798: return arErrorMsg(pAr, "unrecognized option: %s", z); ! 15799: } ! 15800: if( pMatch->bArg ){ ! 15801: if( iArg>=(nArg-1) ){ ! 15802: return arErrorMsg(pAr, "option requires an argument: %s", z); ! 15803: } ! 15804: zArg = azArg[++iArg]; ! 15805: } ! 15806: if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; ! 15807: } ! 15808: } ! 15809: } 1.4 misho 15810: } 1.2 misho 15811: 1.5 ! misho 15812: return SQLITE_OK; 1.3 misho 15813: } 15814: 15815: /* 1.5 ! misho 15816: ** This function assumes that all arguments within the ArCommand.azArg[] ! 15817: ** array refer to archive members, as for the --extract or --list commands. ! 15818: ** It checks that each of them are present. If any specified file is not ! 15819: ** present in the archive, an error is printed to stderr and an error ! 15820: ** code returned. Otherwise, if all specified arguments are present in ! 15821: ** the archive, SQLITE_OK is returned. ! 15822: ** ! 15823: ** This function strips any trailing '/' characters from each argument. ! 15824: ** This is consistent with the way the [tar] command seems to work on ! 15825: ** Linux. ! 15826: */ ! 15827: static int arCheckEntries(ArCommand *pAr){ ! 15828: int rc = SQLITE_OK; ! 15829: if( pAr->nArg ){ ! 15830: int i, j; ! 15831: sqlite3_stmt *pTest = 0; ! 15832: ! 15833: shellPreparePrintf(pAr->db, &rc, &pTest, ! 15834: "SELECT name FROM %s WHERE name=$name", ! 15835: pAr->zSrcTable ! 15836: ); ! 15837: j = sqlite3_bind_parameter_index(pTest, "$name"); ! 15838: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ ! 15839: char *z = pAr->azArg[i]; ! 15840: int n = strlen30(z); ! 15841: int bOk = 0; ! 15842: while( n>0 && z[n-1]=='/' ) n--; ! 15843: z[n] = '\0'; ! 15844: sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); ! 15845: if( SQLITE_ROW==sqlite3_step(pTest) ){ ! 15846: bOk = 1; ! 15847: } ! 15848: shellReset(&rc, pTest); ! 15849: if( rc==SQLITE_OK && bOk==0 ){ ! 15850: utf8_printf(stderr, "not found in archive: %s\n", z); ! 15851: rc = SQLITE_ERROR; ! 15852: } 1.3 misho 15853: } 1.5 ! misho 15854: shellFinalize(&rc, pTest); 1.3 misho 15855: } 1.5 ! misho 15856: return rc; 1.3 misho 15857: } 15858: 15859: /* 1.5 ! misho 15860: ** Format a WHERE clause that can be used against the "sqlar" table to ! 15861: ** identify all archive members that match the command arguments held ! 15862: ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. ! 15863: ** The caller is responsible for eventually calling sqlite3_free() on ! 15864: ** any non-NULL (*pzWhere) value. ! 15865: */ ! 15866: static void arWhereClause( ! 15867: int *pRc, ! 15868: ArCommand *pAr, ! 15869: char **pzWhere /* OUT: New WHERE clause */ ! 15870: ){ ! 15871: char *zWhere = 0; ! 15872: if( *pRc==SQLITE_OK ){ ! 15873: if( pAr->nArg==0 ){ ! 15874: zWhere = sqlite3_mprintf("1"); ! 15875: }else{ ! 15876: int i; ! 15877: const char *zSep = ""; ! 15878: for(i=0; i<pAr->nArg; i++){ ! 15879: const char *z = pAr->azArg[i]; ! 15880: zWhere = sqlite3_mprintf( ! 15881: "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", ! 15882: zWhere, zSep, z, strlen30(z)+1, z ! 15883: ); ! 15884: if( zWhere==0 ){ ! 15885: *pRc = SQLITE_NOMEM; ! 15886: break; ! 15887: } ! 15888: zSep = " OR "; ! 15889: } ! 15890: } 1.4 misho 15891: } 1.5 ! misho 15892: *pzWhere = zWhere; 1.3 misho 15893: } 15894: 15895: /* 1.5 ! misho 15896: ** Implementation of .ar "lisT" command. 1.3 misho 15897: */ 1.5 ! misho 15898: static int arListCommand(ArCommand *pAr){ ! 15899: const char *zSql = "SELECT %s FROM %s WHERE %s"; ! 15900: const char *azCols[] = { ! 15901: "name", ! 15902: "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" ! 15903: }; ! 15904: ! 15905: char *zWhere = 0; ! 15906: sqlite3_stmt *pSql = 0; ! 15907: int rc; ! 15908: ! 15909: rc = arCheckEntries(pAr); ! 15910: arWhereClause(&rc, pAr, &zWhere); ! 15911: ! 15912: shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], ! 15913: pAr->zSrcTable, zWhere); ! 15914: if( pAr->bDryRun ){ ! 15915: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); ! 15916: }else{ ! 15917: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ! 15918: if( pAr->bVerbose ){ ! 15919: utf8_printf(pAr->p->out, "%s % 10d %s %s\n", ! 15920: sqlite3_column_text(pSql, 0), ! 15921: sqlite3_column_int(pSql, 1), ! 15922: sqlite3_column_text(pSql, 2), ! 15923: sqlite3_column_text(pSql, 3) ! 15924: ); ! 15925: }else{ ! 15926: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); ! 15927: } ! 15928: } ! 15929: } ! 15930: shellFinalize(&rc, pSql); ! 15931: sqlite3_free(zWhere); ! 15932: return rc; 1.3 misho 15933: } 15934: 1.5 ! misho 15935: 1.3 misho 15936: /* 1.5 ! misho 15937: ** Implementation of .ar "eXtract" command. 1.4 misho 15938: */ 1.5 ! misho 15939: static int arExtractCommand(ArCommand *pAr){ ! 15940: const char *zSql1 = ! 15941: "SELECT " ! 15942: " ($dir || name)," ! 15943: " writefile(($dir || name), %s, mode, mtime) " ! 15944: "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" ! 15945: " AND name NOT GLOB '*..[/\\]*'"; ! 15946: ! 15947: const char *azExtraArg[] = { ! 15948: "sqlar_uncompress(data, sz)", ! 15949: "data" ! 15950: }; ! 15951: ! 15952: sqlite3_stmt *pSql = 0; ! 15953: int rc = SQLITE_OK; ! 15954: char *zDir = 0; ! 15955: char *zWhere = 0; ! 15956: int i, j; 1.4 misho 15957: 1.5 ! misho 15958: /* If arguments are specified, check that they actually exist within ! 15959: ** the archive before proceeding. And formulate a WHERE clause to ! 15960: ** match them. */ ! 15961: rc = arCheckEntries(pAr); ! 15962: arWhereClause(&rc, pAr, &zWhere); ! 15963: ! 15964: if( rc==SQLITE_OK ){ ! 15965: if( pAr->zDir ){ ! 15966: zDir = sqlite3_mprintf("%s/", pAr->zDir); ! 15967: }else{ ! 15968: zDir = sqlite3_mprintf(""); 1.4 misho 15969: } 1.5 ! misho 15970: if( zDir==0 ) rc = SQLITE_NOMEM; 1.4 misho 15971: } 15972: 1.5 ! misho 15973: shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, ! 15974: azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere ! 15975: ); ! 15976: ! 15977: if( rc==SQLITE_OK ){ ! 15978: j = sqlite3_bind_parameter_index(pSql, "$dir"); ! 15979: sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); ! 15980: ! 15981: /* Run the SELECT statement twice. The first time, writefile() is called ! 15982: ** for all archive members that should be extracted. The second time, ! 15983: ** only for the directories. This is because the timestamps for ! 15984: ** extracted directories must be reset after they are populated (as ! 15985: ** populating them changes the timestamp). */ ! 15986: for(i=0; i<2; i++){ ! 15987: j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); ! 15988: sqlite3_bind_int(pSql, j, i); ! 15989: if( pAr->bDryRun ){ ! 15990: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); ! 15991: }else{ ! 15992: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ! 15993: if( i==0 && pAr->bVerbose ){ ! 15994: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); ! 15995: } 1.4 misho 15996: } 15997: } 1.5 ! misho 15998: shellReset(&rc, pSql); 1.4 misho 15999: } 1.5 ! misho 16000: shellFinalize(&rc, pSql); 1.4 misho 16001: } 1.5 ! misho 16002: ! 16003: sqlite3_free(zDir); ! 16004: sqlite3_free(zWhere); ! 16005: return rc; 1.4 misho 16006: } 16007: 1.5 ! misho 16008: /* ! 16009: ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. 1.4 misho 16010: */ 1.5 ! misho 16011: static int arExecSql(ArCommand *pAr, const char *zSql){ ! 16012: int rc; ! 16013: if( pAr->bDryRun ){ ! 16014: utf8_printf(pAr->p->out, "%s\n", zSql); ! 16015: rc = SQLITE_OK; ! 16016: }else{ ! 16017: char *zErr = 0; ! 16018: rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); ! 16019: if( zErr ){ ! 16020: utf8_printf(stdout, "ERROR: %s\n", zErr); ! 16021: sqlite3_free(zErr); ! 16022: } 1.4 misho 16023: } 1.5 ! misho 16024: return rc; 1.4 misho 16025: } 16026: 1.5 ! misho 16027: 1.4 misho 16028: /* 1.5 ! misho 16029: ** Implementation of .ar "create", "insert", and "update" commands. ! 16030: ** ! 16031: ** create -> Create a new SQL archive ! 16032: ** insert -> Insert or reinsert all files listed ! 16033: ** update -> Insert files that have changed or that were not ! 16034: ** previously in the archive ! 16035: ** ! 16036: ** Create the "sqlar" table in the database if it does not already exist. ! 16037: ** Then add each file in the azFile[] array to the archive. Directories ! 16038: ** are added recursively. If argument bVerbose is non-zero, a message is ! 16039: ** printed on stdout for each file archived. ! 16040: ** ! 16041: ** The create command is the same as update, except that it drops ! 16042: ** any existing "sqlar" table before beginning. The "insert" command ! 16043: ** always overwrites every file named on the command-line, where as ! 16044: ** "update" only overwrites if the size or mtime or mode has changed. ! 16045: */ ! 16046: static int arCreateOrUpdateCommand( ! 16047: ArCommand *pAr, /* Command arguments and options */ ! 16048: int bUpdate, /* true for a --create. */ ! 16049: int bOnlyIfChanged /* Only update if file has changed */ 1.4 misho 16050: ){ 1.5 ! misho 16051: const char *zCreate = ! 16052: "CREATE TABLE IF NOT EXISTS sqlar(\n" ! 16053: " name TEXT PRIMARY KEY, -- name of the file\n" ! 16054: " mode INT, -- access permissions\n" ! 16055: " mtime INT, -- last modification time\n" ! 16056: " sz INT, -- original file size\n" ! 16057: " data BLOB -- compressed content\n" ! 16058: ")"; ! 16059: const char *zDrop = "DROP TABLE IF EXISTS sqlar"; ! 16060: const char *zInsertFmt[2] = { ! 16061: "REPLACE INTO %s(name,mode,mtime,sz,data)\n" ! 16062: " SELECT\n" ! 16063: " %s,\n" ! 16064: " mode,\n" ! 16065: " mtime,\n" ! 16066: " CASE substr(lsmode(mode),1,1)\n" ! 16067: " WHEN '-' THEN length(data)\n" ! 16068: " WHEN 'd' THEN 0\n" ! 16069: " ELSE -1 END,\n" ! 16070: " sqlar_compress(data)\n" ! 16071: " FROM fsdir(%Q,%Q) AS disk\n" ! 16072: " WHERE lsmode(mode) NOT LIKE '?%%'%s;" ! 16073: , ! 16074: "REPLACE INTO %s(name,mode,mtime,data)\n" ! 16075: " SELECT\n" ! 16076: " %s,\n" ! 16077: " mode,\n" ! 16078: " mtime,\n" ! 16079: " data\n" ! 16080: " FROM fsdir(%Q,%Q) AS disk\n" ! 16081: " WHERE lsmode(mode) NOT LIKE '?%%'%s;" ! 16082: }; ! 16083: int i; /* For iterating through azFile[] */ ! 16084: int rc; /* Return code */ ! 16085: const char *zTab = 0; /* SQL table into which to insert */ ! 16086: char *zSql; ! 16087: char zTemp[50]; ! 16088: char *zExists = 0; ! 16089: ! 16090: arExecSql(pAr, "PRAGMA page_size=512"); ! 16091: rc = arExecSql(pAr, "SAVEPOINT ar;"); ! 16092: if( rc!=SQLITE_OK ) return rc; ! 16093: zTemp[0] = 0; ! 16094: if( pAr->bZip ){ ! 16095: /* Initialize the zipfile virtual table, if necessary */ ! 16096: if( pAr->zFile ){ ! 16097: sqlite3_uint64 r; ! 16098: sqlite3_randomness(sizeof(r),&r); ! 16099: sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); ! 16100: zTab = zTemp; ! 16101: zSql = sqlite3_mprintf( ! 16102: "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", ! 16103: zTab, pAr->zFile ! 16104: ); ! 16105: rc = arExecSql(pAr, zSql); ! 16106: sqlite3_free(zSql); ! 16107: }else{ ! 16108: zTab = "zip"; ! 16109: } ! 16110: }else{ ! 16111: /* Initialize the table for an SQLAR */ ! 16112: zTab = "sqlar"; ! 16113: if( bUpdate==0 ){ ! 16114: rc = arExecSql(pAr, zDrop); ! 16115: if( rc!=SQLITE_OK ) goto end_ar_transaction; ! 16116: } ! 16117: rc = arExecSql(pAr, zCreate); ! 16118: } ! 16119: if( bOnlyIfChanged ){ ! 16120: zExists = sqlite3_mprintf( ! 16121: " AND NOT EXISTS(" ! 16122: "SELECT 1 FROM %s AS mem" ! 16123: " WHERE mem.name=disk.name" ! 16124: " AND mem.mtime=disk.mtime" ! 16125: " AND mem.mode=disk.mode)", zTab); ! 16126: }else{ ! 16127: zExists = sqlite3_mprintf(""); 1.4 misho 16128: } 1.5 ! misho 16129: if( zExists==0 ) rc = SQLITE_NOMEM; ! 16130: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ ! 16131: char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, ! 16132: pAr->bVerbose ? "shell_putsnl(name)" : "name", ! 16133: pAr->azArg[i], pAr->zDir, zExists); ! 16134: rc = arExecSql(pAr, zSql2); ! 16135: sqlite3_free(zSql2); 1.4 misho 16136: } 1.5 ! misho 16137: end_ar_transaction: ! 16138: if( rc!=SQLITE_OK ){ ! 16139: sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); ! 16140: }else{ ! 16141: rc = arExecSql(pAr, "RELEASE ar;"); ! 16142: if( pAr->bZip && pAr->zFile ){ ! 16143: zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); ! 16144: arExecSql(pAr, zSql); ! 16145: sqlite3_free(zSql); 1.4 misho 16146: } 1.5 ! misho 16147: } ! 16148: sqlite3_free(zExists); ! 16149: return rc; 1.4 misho 16150: } 16151: 16152: /* 1.5 ! misho 16153: ** Implementation of ".ar" dot command. 1.4 misho 16154: */ 1.5 ! misho 16155: static int arDotCommand( ! 16156: ShellState *pState, /* Current shell tool state */ ! 16157: int fromCmdLine, /* True if -A command-line option, not .ar cmd */ ! 16158: char **azArg, /* Array of arguments passed to dot command */ ! 16159: int nArg /* Number of entries in azArg[] */ 1.4 misho 16160: ){ 1.5 ! misho 16161: ArCommand cmd; 1.4 misho 16162: int rc; 1.5 ! misho 16163: memset(&cmd, 0, sizeof(cmd)); ! 16164: cmd.fromCmdLine = fromCmdLine; ! 16165: rc = arParseCommand(azArg, nArg, &cmd); ! 16166: if( rc==SQLITE_OK ){ ! 16167: int eDbType = SHELL_OPEN_UNSPEC; ! 16168: cmd.p = pState; ! 16169: cmd.db = pState->db; ! 16170: if( cmd.zFile ){ ! 16171: eDbType = deduceDatabaseType(cmd.zFile, 1); ! 16172: }else{ ! 16173: eDbType = pState->openMode; ! 16174: } ! 16175: if( eDbType==SHELL_OPEN_ZIPFILE ){ ! 16176: if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ ! 16177: if( cmd.zFile==0 ){ ! 16178: cmd.zSrcTable = sqlite3_mprintf("zip"); ! 16179: }else{ ! 16180: cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); ! 16181: } ! 16182: } ! 16183: cmd.bZip = 1; ! 16184: }else if( cmd.zFile ){ ! 16185: int flags; ! 16186: if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; ! 16187: if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT ! 16188: || cmd.eCmd==AR_CMD_UPDATE ){ ! 16189: flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; ! 16190: }else{ ! 16191: flags = SQLITE_OPEN_READONLY; ! 16192: } ! 16193: cmd.db = 0; ! 16194: if( cmd.bDryRun ){ ! 16195: utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, ! 16196: eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); ! 16197: } ! 16198: rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, ! 16199: eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); ! 16200: if( rc!=SQLITE_OK ){ ! 16201: utf8_printf(stderr, "cannot open file: %s (%s)\n", ! 16202: cmd.zFile, sqlite3_errmsg(cmd.db) ! 16203: ); ! 16204: goto end_ar_command; ! 16205: } ! 16206: sqlite3_fileio_init(cmd.db, 0, 0); ! 16207: sqlite3_sqlar_init(cmd.db, 0, 0); ! 16208: sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, ! 16209: shellPutsFunc, 0, 0); 1.4 misho 16210: 16211: } 1.5 ! misho 16212: if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ ! 16213: if( cmd.eCmd!=AR_CMD_CREATE ! 16214: && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ! 16215: ){ ! 16216: utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); ! 16217: rc = SQLITE_ERROR; ! 16218: goto end_ar_command; ! 16219: } ! 16220: cmd.zSrcTable = sqlite3_mprintf("sqlar"); ! 16221: } ! 16222: ! 16223: switch( cmd.eCmd ){ ! 16224: case AR_CMD_CREATE: ! 16225: rc = arCreateOrUpdateCommand(&cmd, 0, 0); ! 16226: break; ! 16227: ! 16228: case AR_CMD_EXTRACT: ! 16229: rc = arExtractCommand(&cmd); ! 16230: break; ! 16231: ! 16232: case AR_CMD_LIST: ! 16233: rc = arListCommand(&cmd); ! 16234: break; ! 16235: ! 16236: case AR_CMD_HELP: ! 16237: arUsage(pState->out); ! 16238: break; ! 16239: ! 16240: case AR_CMD_INSERT: ! 16241: rc = arCreateOrUpdateCommand(&cmd, 1, 0); ! 16242: break; ! 16243: ! 16244: default: ! 16245: assert( cmd.eCmd==AR_CMD_UPDATE ); ! 16246: rc = arCreateOrUpdateCommand(&cmd, 1, 1); ! 16247: break; 1.4 misho 16248: } 16249: } 1.5 ! misho 16250: end_ar_command: ! 16251: if( cmd.db!=pState->db ){ ! 16252: close_db(cmd.db); ! 16253: } ! 16254: sqlite3_free(cmd.zSrcTable); ! 16255: ! 16256: return rc; ! 16257: } ! 16258: /* End of the ".archive" or ".ar" command logic ! 16259: *******************************************************************************/ ! 16260: #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ ! 16261: ! 16262: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ! 16263: /* ! 16264: ** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op. ! 16265: ** Otherwise, the SQL statement or statements in zSql are executed using ! 16266: ** database connection db and the error code written to *pRc before ! 16267: ** this function returns. ! 16268: */ ! 16269: static void shellExec(sqlite3 *db, int *pRc, const char *zSql){ ! 16270: int rc = *pRc; ! 16271: if( rc==SQLITE_OK ){ ! 16272: char *zErr = 0; ! 16273: rc = sqlite3_exec(db, zSql, 0, 0, &zErr); ! 16274: if( rc!=SQLITE_OK ){ ! 16275: raw_printf(stderr, "SQL error: %s\n", zErr); 1.4 misho 16276: } 1.5 ! misho 16277: *pRc = rc; 1.4 misho 16278: } 16279: } 16280: 16281: /* 1.5 ! misho 16282: ** Like shellExec(), except that zFmt is a printf() style format string. 1.4 misho 16283: */ 1.5 ! misho 16284: static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){ ! 16285: char *z = 0; ! 16286: if( *pRc==SQLITE_OK ){ ! 16287: va_list ap; ! 16288: va_start(ap, zFmt); ! 16289: z = sqlite3_vmprintf(zFmt, ap); ! 16290: va_end(ap); ! 16291: if( z==0 ){ ! 16292: *pRc = SQLITE_NOMEM; ! 16293: }else{ ! 16294: shellExec(db, pRc, z); ! 16295: } ! 16296: sqlite3_free(z); 1.4 misho 16297: } 16298: } 16299: 16300: /* 1.5 ! misho 16301: ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. ! 16302: ** Otherwise, an attempt is made to allocate, zero and return a pointer ! 16303: ** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set ! 16304: ** to SQLITE_NOMEM and NULL returned. 1.4 misho 16305: */ 1.5 ! misho 16306: static void *shellMalloc(int *pRc, sqlite3_int64 nByte){ ! 16307: void *pRet = 0; ! 16308: if( *pRc==SQLITE_OK ){ ! 16309: pRet = sqlite3_malloc64(nByte); ! 16310: if( pRet==0 ){ ! 16311: *pRc = SQLITE_NOMEM; ! 16312: }else{ ! 16313: memset(pRet, 0, nByte); ! 16314: } 1.4 misho 16315: } 1.5 ! misho 16316: return pRet; 1.4 misho 16317: } 16318: 16319: /* 1.5 ! misho 16320: ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. ! 16321: ** Otherwise, zFmt is treated as a printf() style string. The result of ! 16322: ** formatting it along with any trailing arguments is written into a ! 16323: ** buffer obtained from sqlite3_malloc(), and pointer to which is returned. ! 16324: ** It is the responsibility of the caller to eventually free this buffer ! 16325: ** using a call to sqlite3_free(). ! 16326: ** ! 16327: ** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL ! 16328: ** pointer returned. 1.4 misho 16329: */ 1.5 ! misho 16330: static char *shellMPrintf(int *pRc, const char *zFmt, ...){ ! 16331: char *z = 0; ! 16332: if( *pRc==SQLITE_OK ){ ! 16333: va_list ap; ! 16334: va_start(ap, zFmt); ! 16335: z = sqlite3_vmprintf(zFmt, ap); ! 16336: va_end(ap); ! 16337: if( z==0 ){ ! 16338: *pRc = SQLITE_NOMEM; ! 16339: } 1.4 misho 16340: } 1.5 ! misho 16341: return z; 1.4 misho 16342: } 16343: 16344: /* 1.5 ! misho 16345: ** When running the ".recover" command, each output table, and the special ! 16346: ** orphaned row table if it is required, is represented by an instance ! 16347: ** of the following struct. ! 16348: */ ! 16349: typedef struct RecoverTable RecoverTable; ! 16350: struct RecoverTable { ! 16351: char *zQuoted; /* Quoted version of table name */ ! 16352: int nCol; /* Number of columns in table */ ! 16353: char **azlCol; /* Array of column lists */ ! 16354: int iPk; /* Index of IPK column */ ! 16355: }; ! 16356: ! 16357: /* ! 16358: ** Free a RecoverTable object allocated by recoverFindTable() or ! 16359: ** recoverOrphanTable(). 1.4 misho 16360: */ 1.5 ! misho 16361: static void recoverFreeTable(RecoverTable *pTab){ ! 16362: if( pTab ){ ! 16363: sqlite3_free(pTab->zQuoted); ! 16364: if( pTab->azlCol ){ ! 16365: int i; ! 16366: for(i=0; i<=pTab->nCol; i++){ ! 16367: sqlite3_free(pTab->azlCol[i]); ! 16368: } ! 16369: sqlite3_free(pTab->azlCol); ! 16370: } ! 16371: sqlite3_free(pTab); ! 16372: } 1.4 misho 16373: } 16374: 16375: /* 1.5 ! misho 16376: ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. ! 16377: ** Otherwise, it allocates and returns a RecoverTable object based on the ! 16378: ** final four arguments passed to this function. It is the responsibility ! 16379: ** of the caller to eventually free the returned object using ! 16380: ** recoverFreeTable(). 1.4 misho 16381: */ 1.5 ! misho 16382: static RecoverTable *recoverNewTable( ! 16383: int *pRc, /* IN/OUT: Error code */ ! 16384: const char *zName, /* Name of table */ ! 16385: const char *zSql, /* CREATE TABLE statement */ ! 16386: int bIntkey, ! 16387: int nCol ! 16388: ){ ! 16389: sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */ ! 16390: int rc = *pRc; ! 16391: RecoverTable *pTab = 0; ! 16392: ! 16393: pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable)); ! 16394: if( rc==SQLITE_OK ){ ! 16395: int nSqlCol = 0; ! 16396: int bSqlIntkey = 0; ! 16397: sqlite3_stmt *pStmt = 0; ! 16398: ! 16399: rc = sqlite3_open("", &dbtmp); ! 16400: if( rc==SQLITE_OK ){ ! 16401: sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0, ! 16402: shellIdQuote, 0, 0); ! 16403: } ! 16404: if( rc==SQLITE_OK ){ ! 16405: rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0); ! 16406: } ! 16407: if( rc==SQLITE_OK ){ ! 16408: rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0); ! 16409: if( rc==SQLITE_ERROR ){ ! 16410: rc = SQLITE_OK; ! 16411: goto finished; ! 16412: } ! 16413: } ! 16414: shellPreparePrintf(dbtmp, &rc, &pStmt, ! 16415: "SELECT count(*) FROM pragma_table_info(%Q)", zName ! 16416: ); ! 16417: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16418: nSqlCol = sqlite3_column_int(pStmt, 0); ! 16419: } ! 16420: shellFinalize(&rc, pStmt); ! 16421: ! 16422: if( rc!=SQLITE_OK || nSqlCol<nCol ){ ! 16423: goto finished; ! 16424: } ! 16425: ! 16426: shellPreparePrintf(dbtmp, &rc, &pStmt, ! 16427: "SELECT (" ! 16428: " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage" ! 16429: ") FROM sqlite_schema WHERE name = %Q", zName ! 16430: ); ! 16431: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16432: bSqlIntkey = sqlite3_column_int(pStmt, 0); ! 16433: } ! 16434: shellFinalize(&rc, pStmt); ! 16435: ! 16436: if( bIntkey==bSqlIntkey ){ ! 16437: int i; ! 16438: const char *zPk = "_rowid_"; ! 16439: sqlite3_stmt *pPkFinder = 0; ! 16440: ! 16441: /* If this is an intkey table and there is an INTEGER PRIMARY KEY, ! 16442: ** set zPk to the name of the PK column, and pTab->iPk to the index ! 16443: ** of the column, where columns are 0-numbered from left to right. ! 16444: ** Or, if this is a WITHOUT ROWID table or if there is no IPK column, ! 16445: ** leave zPk as "_rowid_" and pTab->iPk at -2. */ ! 16446: pTab->iPk = -2; ! 16447: if( bIntkey ){ ! 16448: shellPreparePrintf(dbtmp, &rc, &pPkFinder, ! 16449: "SELECT cid, name FROM pragma_table_info(%Q) " ! 16450: " WHERE pk=1 AND type='integer' COLLATE nocase" ! 16451: " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)" ! 16452: , zName, zName ! 16453: ); ! 16454: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){ ! 16455: pTab->iPk = sqlite3_column_int(pPkFinder, 0); ! 16456: zPk = (const char*)sqlite3_column_text(pPkFinder, 1); ! 16457: } ! 16458: } ! 16459: ! 16460: pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName); ! 16461: pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1)); ! 16462: pTab->nCol = nSqlCol; ! 16463: ! 16464: if( bIntkey ){ ! 16465: pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk); ! 16466: }else{ ! 16467: pTab->azlCol[0] = shellMPrintf(&rc, ""); ! 16468: } ! 16469: i = 1; ! 16470: shellPreparePrintf(dbtmp, &rc, &pStmt, ! 16471: "SELECT %Q || group_concat(shell_idquote(name), ', ') " ! 16472: " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) " ! 16473: "FROM pragma_table_info(%Q)", ! 16474: bIntkey ? ", " : "", pTab->iPk, ! 16475: bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ", ! 16476: zName ! 16477: ); ! 16478: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16479: const char *zText = (const char*)sqlite3_column_text(pStmt, 0); ! 16480: pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText); ! 16481: i++; 1.4 misho 16482: } 1.5 ! misho 16483: shellFinalize(&rc, pStmt); ! 16484: ! 16485: shellFinalize(&rc, pPkFinder); 1.4 misho 16486: } 16487: } 1.5 ! misho 16488: ! 16489: finished: ! 16490: sqlite3_close(dbtmp); ! 16491: *pRc = rc; ! 16492: if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){ ! 16493: recoverFreeTable(pTab); ! 16494: pTab = 0; 1.4 misho 16495: } 1.5 ! misho 16496: return pTab; 1.4 misho 16497: } 16498: 16499: /* 1.5 ! misho 16500: ** This function is called to search the schema recovered from the ! 16501: ** sqlite_schema table of the (possibly) corrupt database as part ! 16502: ** of a ".recover" command. Specifically, for a table with root page ! 16503: ** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the ! 16504: ** table must be a WITHOUT ROWID table, or if non-zero, not one of ! 16505: ** those. ! 16506: ** ! 16507: ** If a table is found, a (RecoverTable*) object is returned. Or, if ! 16508: ** no such table is found, but bIntkey is false and iRoot is the ! 16509: ** root page of an index in the recovered schema, then (*pbNoop) is ! 16510: ** set to true and NULL returned. Or, if there is no such table or ! 16511: ** index, NULL is returned and (*pbNoop) set to 0, indicating that ! 16512: ** the caller should write data to the orphans table. ! 16513: */ ! 16514: static RecoverTable *recoverFindTable( ! 16515: ShellState *pState, /* Shell state object */ ! 16516: int *pRc, /* IN/OUT: Error code */ ! 16517: int iRoot, /* Root page of table */ ! 16518: int bIntkey, /* True for an intkey table */ ! 16519: int nCol, /* Number of columns in table */ ! 16520: int *pbNoop /* OUT: True if iRoot is root of index */ ! 16521: ){ ! 16522: sqlite3_stmt *pStmt = 0; ! 16523: RecoverTable *pRet = 0; ! 16524: int bNoop = 0; ! 16525: const char *zSql = 0; ! 16526: const char *zName = 0; ! 16527: ! 16528: /* Search the recovered schema for an object with root page iRoot. */ ! 16529: shellPreparePrintf(pState->db, pRc, &pStmt, ! 16530: "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot ! 16531: ); ! 16532: while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16533: const char *zType = (const char*)sqlite3_column_text(pStmt, 0); ! 16534: if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){ ! 16535: bNoop = 1; ! 16536: break; ! 16537: } ! 16538: if( sqlite3_stricmp(zType, "table")==0 ){ ! 16539: zName = (const char*)sqlite3_column_text(pStmt, 1); ! 16540: zSql = (const char*)sqlite3_column_text(pStmt, 2); ! 16541: pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol); ! 16542: break; ! 16543: } ! 16544: } ! 16545: ! 16546: shellFinalize(pRc, pStmt); ! 16547: *pbNoop = bNoop; ! 16548: return pRet; 1.4 misho 16549: } 16550: 16551: /* 1.5 ! misho 16552: ** Return a RecoverTable object representing the orphans table. 1.4 misho 16553: */ 1.5 ! misho 16554: static RecoverTable *recoverOrphanTable( ! 16555: ShellState *pState, /* Shell state object */ ! 16556: int *pRc, /* IN/OUT: Error code */ ! 16557: const char *zLostAndFound, /* Base name for orphans table */ ! 16558: int nCol /* Number of user data columns */ ! 16559: ){ ! 16560: RecoverTable *pTab = 0; ! 16561: if( nCol>=0 && *pRc==SQLITE_OK ){ ! 16562: int i; ! 16563: ! 16564: /* This block determines the name of the orphan table. The prefered ! 16565: ** name is zLostAndFound. But if that clashes with another name ! 16566: ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1 ! 16567: ** and so on until a non-clashing name is found. */ ! 16568: int iTab = 0; ! 16569: char *zTab = shellMPrintf(pRc, "%s", zLostAndFound); ! 16570: sqlite3_stmt *pTest = 0; ! 16571: shellPrepare(pState->db, pRc, ! 16572: "SELECT 1 FROM recovery.schema WHERE name=?", &pTest ! 16573: ); ! 16574: if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); ! 16575: while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){ ! 16576: shellReset(pRc, pTest); ! 16577: sqlite3_free(zTab); ! 16578: zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++); ! 16579: sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); ! 16580: } ! 16581: shellFinalize(pRc, pTest); ! 16582: ! 16583: pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable)); ! 16584: if( pTab ){ ! 16585: pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab); ! 16586: pTab->nCol = nCol; ! 16587: pTab->iPk = -2; ! 16588: if( nCol>0 ){ ! 16589: pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1)); ! 16590: if( pTab->azlCol ){ ! 16591: pTab->azlCol[nCol] = shellMPrintf(pRc, ""); ! 16592: for(i=nCol-1; i>=0; i--){ ! 16593: pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]); ! 16594: } ! 16595: } ! 16596: } ! 16597: ! 16598: if( *pRc!=SQLITE_OK ){ ! 16599: recoverFreeTable(pTab); ! 16600: pTab = 0; ! 16601: }else{ ! 16602: raw_printf(pState->out, ! 16603: "CREATE TABLE %s(rootpgno INTEGER, " ! 16604: "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted ! 16605: ); ! 16606: for(i=0; i<nCol; i++){ ! 16607: raw_printf(pState->out, ", c%d", i); ! 16608: } ! 16609: raw_printf(pState->out, ");\n"); ! 16610: } ! 16611: } ! 16612: sqlite3_free(zTab); ! 16613: } ! 16614: return pTab; 1.4 misho 16615: } 16616: 16617: /* 1.5 ! misho 16618: ** This function is called to recover data from the database. A script ! 16619: ** to construct a new database containing all recovered data is output ! 16620: ** on stream pState->out. 1.4 misho 16621: */ 1.5 ! misho 16622: static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ ! 16623: int rc = SQLITE_OK; ! 16624: sqlite3_stmt *pLoop = 0; /* Loop through all root pages */ ! 16625: sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */ ! 16626: sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */ ! 16627: const char *zRecoveryDb = ""; /* Name of "recovery" database */ ! 16628: const char *zLostAndFound = "lost_and_found"; ! 16629: int i; ! 16630: int nOrphan = -1; ! 16631: RecoverTable *pOrphan = 0; ! 16632: ! 16633: int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ ! 16634: int bRowids = 1; /* 0 if --no-rowids */ ! 16635: for(i=1; i<nArg; i++){ ! 16636: char *z = azArg[i]; ! 16637: int n; ! 16638: if( z[0]=='-' && z[1]=='-' ) z++; ! 16639: n = strlen30(z); ! 16640: if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){ ! 16641: bFreelist = 0; ! 16642: }else ! 16643: if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){ ! 16644: i++; ! 16645: zRecoveryDb = azArg[i]; ! 16646: }else ! 16647: if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){ ! 16648: i++; ! 16649: zLostAndFound = azArg[i]; ! 16650: }else ! 16651: if( n<=10 && memcmp("-no-rowids", z, n)==0 ){ ! 16652: bRowids = 0; ! 16653: } ! 16654: else{ ! 16655: utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); ! 16656: showHelp(pState->out, azArg[0]); ! 16657: return 1; ! 16658: } ! 16659: } ! 16660: ! 16661: shellExecPrintf(pState->db, &rc, ! 16662: /* Attach an in-memory database named 'recovery'. Create an indexed ! 16663: ** cache of the sqlite_dbptr virtual table. */ ! 16664: "PRAGMA writable_schema = on;" ! 16665: "ATTACH %Q AS recovery;" ! 16666: "DROP TABLE IF EXISTS recovery.dbptr;" ! 16667: "DROP TABLE IF EXISTS recovery.freelist;" ! 16668: "DROP TABLE IF EXISTS recovery.map;" ! 16669: "DROP TABLE IF EXISTS recovery.schema;" ! 16670: "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb ! 16671: ); ! 16672: ! 16673: if( bFreelist ){ ! 16674: shellExec(pState->db, &rc, ! 16675: "WITH trunk(pgno) AS (" ! 16676: " SELECT shell_int32(" ! 16677: " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x " ! 16678: " WHERE x>0" ! 16679: " UNION" ! 16680: " SELECT shell_int32(" ! 16681: " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x " ! 16682: " FROM trunk WHERE x>0" ! 16683: ")," ! 16684: "freelist(data, n, freepgno) AS (" ! 16685: " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno " ! 16686: " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno" ! 16687: " UNION ALL" ! 16688: " SELECT data, n-1, shell_int32(data, 2+n) " ! 16689: " FROM freelist WHERE n>=0" ! 16690: ")" ! 16691: "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;" ! 16692: ); ! 16693: } ! 16694: ! 16695: /* If this is an auto-vacuum database, add all pointer-map pages to ! 16696: ** the freelist table. Do this regardless of whether or not ! 16697: ** --freelist-corrupt was specified. */ ! 16698: shellExec(pState->db, &rc, ! 16699: "WITH ptrmap(pgno) AS (" ! 16700: " SELECT 2 WHERE shell_int32(" ! 16701: " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13" ! 16702: " )" ! 16703: " UNION ALL " ! 16704: " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp " ! 16705: " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)" ! 16706: ")" ! 16707: "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap" ! 16708: ); ! 16709: ! 16710: shellExec(pState->db, &rc, ! 16711: "CREATE TABLE recovery.dbptr(" ! 16712: " pgno, child, PRIMARY KEY(child, pgno)" ! 16713: ") WITHOUT ROWID;" ! 16714: "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) " ! 16715: " SELECT * FROM sqlite_dbptr" ! 16716: " WHERE pgno NOT IN freelist AND child NOT IN freelist;" ! 16717: ! 16718: /* Delete any pointer to page 1. This ensures that page 1 is considered ! 16719: ** a root page, regardless of how corrupt the db is. */ ! 16720: "DELETE FROM recovery.dbptr WHERE child = 1;" ! 16721: ! 16722: /* Delete all pointers to any pages that have more than one pointer ! 16723: ** to them. Such pages will be treated as root pages when recovering ! 16724: ** data. */ ! 16725: "DELETE FROM recovery.dbptr WHERE child IN (" ! 16726: " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1" ! 16727: ");" ! 16728: ! 16729: /* Create the "map" table that will (eventually) contain instructions ! 16730: ** for dealing with each page in the db that contains one or more ! 16731: ** records. */ ! 16732: "CREATE TABLE recovery.map(" ! 16733: "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT" ! 16734: ");" ! 16735: ! 16736: /* Populate table [map]. If there are circular loops of pages in the ! 16737: ** database, the following adds all pages in such a loop to the map ! 16738: ** as individual root pages. This could be handled better. */ ! 16739: "WITH pages(i, maxlen) AS (" ! 16740: " SELECT page_count, (" ! 16741: " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count" ! 16742: " ) FROM pragma_page_count WHERE page_count>0" ! 16743: " UNION ALL" ! 16744: " SELECT i-1, (" ! 16745: " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1" ! 16746: " ) FROM pages WHERE i>=2" ! 16747: ")" ! 16748: "INSERT INTO recovery.map(pgno, maxlen, intkey, root) " ! 16749: " SELECT i, maxlen, NULL, (" ! 16750: " WITH p(orig, pgno, parent) AS (" ! 16751: " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)" ! 16752: " UNION " ! 16753: " SELECT i, p.parent, " ! 16754: " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p" ! 16755: " )" ! 16756: " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" ! 16757: ") " ! 16758: "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;" ! 16759: "UPDATE recovery.map AS o SET intkey = (" ! 16760: " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" ! 16761: ");" ! 16762: ! 16763: /* Extract data from page 1 and any linked pages into table ! 16764: ** recovery.schema. With the same schema as an sqlite_schema table. */ ! 16765: "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);" ! 16766: "INSERT INTO recovery.schema SELECT " ! 16767: " max(CASE WHEN field=0 THEN value ELSE NULL END)," ! 16768: " max(CASE WHEN field=1 THEN value ELSE NULL END)," ! 16769: " max(CASE WHEN field=2 THEN value ELSE NULL END)," ! 16770: " max(CASE WHEN field=3 THEN value ELSE NULL END)," ! 16771: " max(CASE WHEN field=4 THEN value ELSE NULL END)" ! 16772: "FROM sqlite_dbdata WHERE pgno IN (" ! 16773: " SELECT pgno FROM recovery.map WHERE root=1" ! 16774: ")" ! 16775: "GROUP BY pgno, cell;" ! 16776: "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);" ! 16777: ); ! 16778: ! 16779: /* Open a transaction, then print out all non-virtual, non-"sqlite_%" ! 16780: ** CREATE TABLE statements that extracted from the existing schema. */ ! 16781: if( rc==SQLITE_OK ){ ! 16782: sqlite3_stmt *pStmt = 0; ! 16783: /* ".recover" might output content in an order which causes immediate ! 16784: ** foreign key constraints to be violated. So disable foreign-key ! 16785: ** constraint enforcement to prevent problems when running the output ! 16786: ** script. */ ! 16787: raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n"); ! 16788: raw_printf(pState->out, "BEGIN;\n"); ! 16789: raw_printf(pState->out, "PRAGMA writable_schema = on;\n"); ! 16790: shellPrepare(pState->db, &rc, ! 16791: "SELECT sql FROM recovery.schema " ! 16792: "WHERE type='table' AND sql LIKE 'create table%'", &pStmt ! 16793: ); ! 16794: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16795: const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0); ! 16796: raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", ! 16797: &zCreateTable[12] ! 16798: ); ! 16799: } ! 16800: shellFinalize(&rc, pStmt); ! 16801: } ! 16802: ! 16803: /* Figure out if an orphan table will be required. And if so, how many ! 16804: ** user columns it should contain */ ! 16805: shellPrepare(pState->db, &rc, ! 16806: "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1" ! 16807: , &pLoop ! 16808: ); ! 16809: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ ! 16810: nOrphan = sqlite3_column_int(pLoop, 0); ! 16811: } ! 16812: shellFinalize(&rc, pLoop); ! 16813: pLoop = 0; ! 16814: ! 16815: shellPrepare(pState->db, &rc, ! 16816: "SELECT pgno FROM recovery.map WHERE root=?", &pPages ! 16817: ); ! 16818: ! 16819: shellPrepare(pState->db, &rc, ! 16820: "SELECT max(field), group_concat(shell_escape_crnl(quote" ! 16821: "(case when (? AND field<0) then NULL else value end)" ! 16822: "), ', ')" ! 16823: ", min(field) " ! 16824: "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" ! 16825: "GROUP BY cell", &pCells ! 16826: ); ! 16827: ! 16828: /* Loop through each root page. */ ! 16829: shellPrepare(pState->db, &rc, ! 16830: "SELECT root, intkey, max(maxlen) FROM recovery.map" ! 16831: " WHERE root>1 GROUP BY root, intkey ORDER BY root=(" ! 16832: " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'" ! 16833: ")", &pLoop ! 16834: ); ! 16835: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ ! 16836: int iRoot = sqlite3_column_int(pLoop, 0); ! 16837: int bIntkey = sqlite3_column_int(pLoop, 1); ! 16838: int nCol = sqlite3_column_int(pLoop, 2); ! 16839: int bNoop = 0; ! 16840: RecoverTable *pTab; ! 16841: ! 16842: assert( bIntkey==0 || bIntkey==1 ); ! 16843: pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop); ! 16844: if( bNoop || rc ) continue; ! 16845: if( pTab==0 ){ ! 16846: if( pOrphan==0 ){ ! 16847: pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); ! 16848: } ! 16849: pTab = pOrphan; ! 16850: if( pTab==0 ) break; ! 16851: } ! 16852: ! 16853: if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){ ! 16854: raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); ! 16855: } ! 16856: sqlite3_bind_int(pPages, 1, iRoot); ! 16857: if( bRowids==0 && pTab->iPk<0 ){ ! 16858: sqlite3_bind_int(pCells, 1, 1); ! 16859: }else{ ! 16860: sqlite3_bind_int(pCells, 1, 0); ! 16861: } ! 16862: sqlite3_bind_int(pCells, 3, pTab->iPk); ! 16863: ! 16864: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ ! 16865: int iPgno = sqlite3_column_int(pPages, 0); ! 16866: sqlite3_bind_int(pCells, 2, iPgno); ! 16867: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ ! 16868: int nField = sqlite3_column_int(pCells, 0); ! 16869: int iMin = sqlite3_column_int(pCells, 2); ! 16870: const char *zVal = (const char*)sqlite3_column_text(pCells, 1); ! 16871: ! 16872: RecoverTable *pTab2 = pTab; ! 16873: if( pTab!=pOrphan && (iMin<0)!=bIntkey ){ ! 16874: if( pOrphan==0 ){ ! 16875: pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); ! 16876: } ! 16877: pTab2 = pOrphan; ! 16878: if( pTab2==0 ) break; ! 16879: } ! 16880: ! 16881: nField = nField+1; ! 16882: if( pTab2==pOrphan ){ ! 16883: raw_printf(pState->out, ! 16884: "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n", ! 16885: pTab2->zQuoted, iRoot, iPgno, nField, ! 16886: iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField] ! 16887: ); ! 16888: }else{ ! 16889: raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", ! 16890: pTab2->zQuoted, pTab2->azlCol[nField], zVal ! 16891: ); ! 16892: } ! 16893: } ! 16894: shellReset(&rc, pCells); ! 16895: } ! 16896: shellReset(&rc, pPages); ! 16897: if( pTab!=pOrphan ) recoverFreeTable(pTab); ! 16898: } ! 16899: shellFinalize(&rc, pLoop); ! 16900: shellFinalize(&rc, pPages); ! 16901: shellFinalize(&rc, pCells); ! 16902: recoverFreeTable(pOrphan); ! 16903: ! 16904: /* The rest of the schema */ ! 16905: if( rc==SQLITE_OK ){ ! 16906: sqlite3_stmt *pStmt = 0; ! 16907: shellPrepare(pState->db, &rc, ! 16908: "SELECT sql, name FROM recovery.schema " ! 16909: "WHERE sql NOT LIKE 'create table%'", &pStmt ! 16910: ); ! 16911: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ ! 16912: const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); ! 16913: if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){ ! 16914: const char *zName = (const char*)sqlite3_column_text(pStmt, 1); ! 16915: char *zPrint = shellMPrintf(&rc, ! 16916: "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)", ! 16917: zName, zName, zSql ! 16918: ); ! 16919: raw_printf(pState->out, "%s;\n", zPrint); ! 16920: sqlite3_free(zPrint); ! 16921: }else{ ! 16922: raw_printf(pState->out, "%s;\n", zSql); ! 16923: } ! 16924: } ! 16925: shellFinalize(&rc, pStmt); ! 16926: } ! 16927: ! 16928: if( rc==SQLITE_OK ){ ! 16929: raw_printf(pState->out, "PRAGMA writable_schema = off;\n"); ! 16930: raw_printf(pState->out, "COMMIT;\n"); ! 16931: } ! 16932: sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); ! 16933: return rc; 1.4 misho 16934: } 1.5 ! misho 16935: #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ ! 16936: 1.4 misho 16937: 16938: /* 1.2 misho 16939: ** If an input line begins with "." then invoke this routine to 16940: ** process that line. 16941: ** 16942: ** Return 1 on error, 2 to exit, and 0 otherwise. 16943: */ 1.4 misho 16944: static int do_meta_command(char *zLine, ShellState *p){ 16945: int h = 1; 1.2 misho 16946: int nArg = 0; 16947: int n, c; 16948: int rc = 0; 1.5 ! misho 16949: char *azArg[52]; ! 16950: ! 16951: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 16952: if( p->expert.pExpert ){ ! 16953: expertFinish(p, 1, 0); ! 16954: } ! 16955: #endif 1.2 misho 16956: 16957: /* Parse the input line into tokens. 16958: */ 1.5 ! misho 16959: while( zLine[h] && nArg<ArraySize(azArg)-1 ){ 1.4 misho 16960: while( IsSpace(zLine[h]) ){ h++; } 16961: if( zLine[h]==0 ) break; 16962: if( zLine[h]=='\'' || zLine[h]=='"' ){ 16963: int delim = zLine[h++]; 16964: azArg[nArg++] = &zLine[h]; 16965: while( zLine[h] && zLine[h]!=delim ){ 16966: if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++; 16967: h++; 16968: } 16969: if( zLine[h]==delim ){ 16970: zLine[h++] = 0; 1.2 misho 16971: } 16972: if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); 16973: }else{ 1.4 misho 16974: azArg[nArg++] = &zLine[h]; 16975: while( zLine[h] && !IsSpace(zLine[h]) ){ h++; } 16976: if( zLine[h] ) zLine[h++] = 0; 1.2 misho 16977: resolve_backslashes(azArg[nArg-1]); 16978: } 16979: } 1.5 ! misho 16980: azArg[nArg] = 0; 1.2 misho 16981: 16982: /* Process the input line. 16983: */ 16984: if( nArg==0 ) return 0; /* no tokens, no error */ 16985: n = strlen30(azArg[0]); 16986: c = azArg[0][0]; 1.5 ! misho 16987: clearTempFile(p); 1.4 misho 16988: 1.5 ! misho 16989: #ifndef SQLITE_OMIT_AUTHORIZATION 1.4 misho 16990: if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ 16991: if( nArg!=2 ){ 16992: raw_printf(stderr, "Usage: .auth ON|OFF\n"); 16993: rc = 1; 16994: goto meta_command_exit; 16995: } 16996: open_db(p, 0); 16997: if( booleanValue(azArg[1]) ){ 16998: sqlite3_set_authorizer(p->db, shellAuth, p); 16999: }else{ 17000: sqlite3_set_authorizer(p->db, 0, 0); 17001: } 17002: }else 1.5 ! misho 17003: #endif ! 17004: ! 17005: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ! 17006: if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){ ! 17007: open_db(p, 0); ! 17008: rc = arDotCommand(p, 0, azArg, nArg); ! 17009: }else ! 17010: #endif 1.4 misho 17011: 17012: if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) 17013: || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) 17014: ){ 17015: const char *zDestFile = 0; 17016: const char *zDb = 0; 1.2 misho 17017: sqlite3 *pDest; 17018: sqlite3_backup *pBackup; 1.4 misho 17019: int j; 1.5 ! misho 17020: int bAsync = 0; ! 17021: const char *zVfs = 0; 1.4 misho 17022: for(j=1; j<nArg; j++){ 17023: const char *z = azArg[j]; 17024: if( z[0]=='-' ){ 1.5 ! misho 17025: if( z[1]=='-' ) z++; ! 17026: if( strcmp(z, "-append")==0 ){ ! 17027: zVfs = "apndvfs"; ! 17028: }else ! 17029: if( strcmp(z, "-async")==0 ){ ! 17030: bAsync = 1; ! 17031: }else 1.4 misho 17032: { 17033: utf8_printf(stderr, "unknown option: %s\n", azArg[j]); 17034: return 1; 17035: } 17036: }else if( zDestFile==0 ){ 17037: zDestFile = azArg[j]; 17038: }else if( zDb==0 ){ 17039: zDb = zDestFile; 17040: zDestFile = azArg[j]; 17041: }else{ 1.5 ! misho 17042: raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n"); 1.4 misho 17043: return 1; 17044: } 17045: } 17046: if( zDestFile==0 ){ 17047: raw_printf(stderr, "missing FILENAME argument on .backup\n"); 17048: return 1; 1.2 misho 17049: } 1.4 misho 17050: if( zDb==0 ) zDb = "main"; 1.5 ! misho 17051: rc = sqlite3_open_v2(zDestFile, &pDest, ! 17052: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs); 1.2 misho 17053: if( rc!=SQLITE_OK ){ 1.4 misho 17054: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); 1.5 ! misho 17055: close_db(pDest); 1.2 misho 17056: return 1; 17057: } 1.5 ! misho 17058: if( bAsync ){ ! 17059: sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;", ! 17060: 0, 0, 0); ! 17061: } 1.4 misho 17062: open_db(p, 0); 1.2 misho 17063: pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); 17064: if( pBackup==0 ){ 1.4 misho 17065: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); 1.5 ! misho 17066: close_db(pDest); 1.2 misho 17067: return 1; 17068: } 17069: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} 17070: sqlite3_backup_finish(pBackup); 17071: if( rc==SQLITE_DONE ){ 17072: rc = 0; 17073: }else{ 1.4 misho 17074: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); 1.2 misho 17075: rc = 1; 17076: } 1.5 ! misho 17077: close_db(pDest); 1.2 misho 17078: }else 17079: 1.4 misho 17080: if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ 17081: if( nArg==2 ){ 17082: bail_on_error = booleanValue(azArg[1]); 17083: }else{ 17084: raw_printf(stderr, "Usage: .bail on|off\n"); 17085: rc = 1; 17086: } 17087: }else 17088: 17089: if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ 17090: if( nArg==2 ){ 17091: if( booleanValue(azArg[1]) ){ 17092: setBinaryMode(p->out, 1); 17093: }else{ 17094: setTextMode(p->out, 1); 17095: } 17096: }else{ 17097: raw_printf(stderr, "Usage: .binary on|off\n"); 17098: rc = 1; 17099: } 1.2 misho 17100: }else 17101: 1.5 ! misho 17102: if( c=='c' && strcmp(azArg[0],"cd")==0 ){ ! 17103: if( nArg==2 ){ ! 17104: #if defined(_WIN32) || defined(WIN32) ! 17105: wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); ! 17106: rc = !SetCurrentDirectoryW(z); ! 17107: sqlite3_free(z); ! 17108: #else ! 17109: rc = chdir(azArg[1]); ! 17110: #endif ! 17111: if( rc ){ ! 17112: utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); ! 17113: rc = 1; ! 17114: } ! 17115: }else{ ! 17116: raw_printf(stderr, "Usage: .cd DIRECTORY\n"); ! 17117: rc = 1; ! 17118: } ! 17119: }else ! 17120: 1.3 misho 17121: /* The undocumented ".breakpoint" command causes a call to the no-op 17122: ** routine named test_breakpoint(). 17123: */ 17124: if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ 17125: test_breakpoint(); 17126: }else 17127: 1.4 misho 17128: if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ 17129: if( nArg==2 ){ 1.5 ! misho 17130: setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); 1.4 misho 17131: }else{ 17132: raw_printf(stderr, "Usage: .changes on|off\n"); 17133: rc = 1; 17134: } 17135: }else 17136: 1.5 ! misho 17137: /* Cancel output redirection, if it is currently set (by .testcase) ! 17138: ** Then read the content of the testcase-out.txt file and compare against ! 17139: ** azArg[1]. If there are differences, report an error and exit. ! 17140: */ ! 17141: if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){ ! 17142: char *zRes = 0; ! 17143: output_reset(p); ! 17144: if( nArg!=2 ){ ! 17145: raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); ! 17146: rc = 2; ! 17147: }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ ! 17148: raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n"); ! 17149: rc = 2; ! 17150: }else if( testcase_glob(azArg[1],zRes)==0 ){ ! 17151: utf8_printf(stderr, ! 17152: "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", ! 17153: p->zTestcase, azArg[1], zRes); ! 17154: rc = 1; ! 17155: }else{ ! 17156: utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); ! 17157: p->nCheck++; ! 17158: } ! 17159: sqlite3_free(zRes); ! 17160: }else ! 17161: 1.4 misho 17162: if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ 17163: if( nArg==2 ){ 17164: tryToClone(p, azArg[1]); 17165: }else{ 17166: raw_printf(stderr, "Usage: .clone FILENAME\n"); 17167: rc = 1; 17168: } 17169: }else 17170: 17171: if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ 17172: ShellState data; 1.2 misho 17173: char *zErrMsg = 0; 1.4 misho 17174: open_db(p, 0); 1.2 misho 17175: memcpy(&data, p, sizeof(data)); 1.5 ! misho 17176: data.showHeader = 0; ! 17177: data.cMode = data.mode = MODE_List; ! 17178: sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": "); 1.2 misho 17179: data.cnt = 0; 1.5 ! misho 17180: sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list", ! 17181: callback, &data, &zErrMsg); 1.2 misho 17182: if( zErrMsg ){ 1.4 misho 17183: utf8_printf(stderr,"Error: %s\n", zErrMsg); 1.2 misho 17184: sqlite3_free(zErrMsg); 17185: rc = 1; 17186: } 17187: }else 17188: 1.5 ! misho 17189: if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ ! 17190: static const struct DbConfigChoices { ! 17191: const char *zName; ! 17192: int op; ! 17193: } aDbConfig[] = { ! 17194: { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, ! 17195: { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, ! 17196: { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, ! 17197: { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, ! 17198: { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, ! 17199: { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, ! 17200: { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, ! 17201: { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, ! 17202: { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, ! 17203: { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, ! 17204: { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, ! 17205: { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, ! 17206: { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, ! 17207: { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, ! 17208: { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, ! 17209: { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, ! 17210: }; ! 17211: int ii, v; ! 17212: open_db(p, 0); ! 17213: for(ii=0; ii<ArraySize(aDbConfig); ii++){ ! 17214: if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; ! 17215: if( nArg>=3 ){ ! 17216: sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); ! 17217: } ! 17218: sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); ! 17219: utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); ! 17220: if( nArg>1 ) break; ! 17221: } ! 17222: if( nArg>1 && ii==ArraySize(aDbConfig) ){ ! 17223: utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); ! 17224: utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); ! 17225: } ! 17226: }else ! 17227: ! 17228: if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ 1.4 misho 17229: rc = shell_dbinfo_command(p, nArg, azArg); 17230: }else 17231: 1.5 ! misho 17232: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ! 17233: if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){ ! 17234: open_db(p, 0); ! 17235: rc = recoverDatabaseCmd(p, nArg, azArg); ! 17236: }else ! 17237: #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ ! 17238: 1.4 misho 17239: if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ 1.5 ! misho 17240: char *zLike = 0; ! 17241: char *zSql; ! 17242: int i; ! 17243: int savedShowHeader = p->showHeader; ! 17244: int savedShellFlags = p->shellFlgs; ! 17245: ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo); ! 17246: for(i=1; i<nArg; i++){ ! 17247: if( azArg[i][0]=='-' ){ ! 17248: const char *z = azArg[i]+1; ! 17249: if( z[0]=='-' ) z++; ! 17250: if( strcmp(z,"preserve-rowids")==0 ){ ! 17251: #ifdef SQLITE_OMIT_VIRTUALTABLE ! 17252: raw_printf(stderr, "The --preserve-rowids option is not compatible" ! 17253: " with SQLITE_OMIT_VIRTUALTABLE\n"); ! 17254: rc = 1; ! 17255: sqlite3_free(zLike); ! 17256: goto meta_command_exit; ! 17257: #else ! 17258: ShellSetFlag(p, SHFLG_PreserveRowid); ! 17259: #endif ! 17260: }else ! 17261: if( strcmp(z,"newlines")==0 ){ ! 17262: ShellSetFlag(p, SHFLG_Newlines); ! 17263: }else ! 17264: { ! 17265: raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]); ! 17266: rc = 1; ! 17267: sqlite3_free(zLike); ! 17268: goto meta_command_exit; ! 17269: } ! 17270: }else if( zLike ){ ! 17271: zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'", ! 17272: zLike, azArg[i]); ! 17273: }else{ ! 17274: zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]); ! 17275: } ! 17276: } ! 17277: 1.4 misho 17278: open_db(p, 0); 1.5 ! misho 17279: 1.2 misho 17280: /* When playing back a "dump", the content might appear in an order 17281: ** which causes immediate foreign key constraints to be violated. 17282: ** So disable foreign-key constraint enforcement to prevent problems. */ 1.4 misho 17283: raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); 17284: raw_printf(p->out, "BEGIN TRANSACTION;\n"); 1.2 misho 17285: p->writableSchema = 0; 1.5 ! misho 17286: p->showHeader = 0; ! 17287: /* Set writable_schema=ON since doing so forces SQLite to initialize ! 17288: ** as much of the schema as it can even if the sqlite_schema table is ! 17289: ** corrupt. */ 1.2 misho 17290: sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); 17291: p->nErr = 0; 1.5 ! misho 17292: if( zLike==0 ) zLike = sqlite3_mprintf("true"); ! 17293: zSql = sqlite3_mprintf( ! 17294: "SELECT name, type, sql FROM sqlite_schema " ! 17295: "WHERE (%s) AND type=='table'" ! 17296: " AND sql NOT NULL" ! 17297: " ORDER BY tbl_name='sqlite_sequence', rowid", ! 17298: zLike ! 17299: ); ! 17300: run_schema_dump_query(p,zSql); ! 17301: sqlite3_free(zSql); ! 17302: zSql = sqlite3_mprintf( ! 17303: "SELECT sql FROM sqlite_schema " ! 17304: "WHERE (%s) AND sql NOT NULL" ! 17305: " AND type IN ('index','trigger','view')", ! 17306: zLike ! 17307: ); ! 17308: run_table_dump_query(p, zSql); ! 17309: sqlite3_free(zSql); ! 17310: sqlite3_free(zLike); 1.2 misho 17311: if( p->writableSchema ){ 1.4 misho 17312: raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); 1.2 misho 17313: p->writableSchema = 0; 17314: } 17315: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); 17316: sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); 1.5 ! misho 17317: raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); ! 17318: p->showHeader = savedShowHeader; ! 17319: p->shellFlgs = savedShellFlags; 1.4 misho 17320: }else 17321: 17322: if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ 17323: if( nArg==2 ){ 1.5 ! misho 17324: setOrClearFlag(p, SHFLG_Echo, azArg[1]); 1.4 misho 17325: }else{ 17326: raw_printf(stderr, "Usage: .echo on|off\n"); 17327: rc = 1; 17328: } 1.2 misho 17329: }else 17330: 1.4 misho 17331: if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ 17332: if( nArg==2 ){ 1.5 ! misho 17333: p->autoEQPtest = 0; ! 17334: if( p->autoEQPtrace ){ ! 17335: if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0); ! 17336: p->autoEQPtrace = 0; ! 17337: } 1.4 misho 17338: if( strcmp(azArg[1],"full")==0 ){ 1.5 ! misho 17339: p->autoEQP = AUTOEQP_full; ! 17340: }else if( strcmp(azArg[1],"trigger")==0 ){ ! 17341: p->autoEQP = AUTOEQP_trigger; ! 17342: #ifdef SQLITE_DEBUG ! 17343: }else if( strcmp(azArg[1],"test")==0 ){ ! 17344: p->autoEQP = AUTOEQP_on; ! 17345: p->autoEQPtest = 1; ! 17346: }else if( strcmp(azArg[1],"trace")==0 ){ ! 17347: p->autoEQP = AUTOEQP_full; ! 17348: p->autoEQPtrace = 1; ! 17349: open_db(p, 0); ! 17350: sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0); ! 17351: sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0); ! 17352: #endif 1.4 misho 17353: }else{ 1.5 ! misho 17354: p->autoEQP = (u8)booleanValue(azArg[1]); 1.4 misho 17355: } 17356: }else{ 1.5 ! misho 17357: raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n"); 1.4 misho 17358: rc = 1; 17359: } 1.2 misho 17360: }else 17361: 1.4 misho 17362: if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ 17363: if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); 1.2 misho 17364: rc = 2; 17365: }else 17366: 1.5 ! misho 17367: /* The ".explain" command is automatic now. It is largely pointless. It ! 17368: ** retained purely for backwards compatibility */ 1.4 misho 17369: if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ 17370: int val = 1; 17371: if( nArg>=2 ){ 17372: if( strcmp(azArg[1],"auto")==0 ){ 17373: val = 99; 17374: }else{ 17375: val = booleanValue(azArg[1]); 17376: } 17377: } 17378: if( val==1 && p->mode!=MODE_Explain ){ 17379: p->normalMode = p->mode; 1.2 misho 17380: p->mode = MODE_Explain; 1.4 misho 17381: p->autoExplain = 0; 17382: }else if( val==0 ){ 17383: if( p->mode==MODE_Explain ) p->mode = p->normalMode; 17384: p->autoExplain = 0; 17385: }else if( val==99 ){ 17386: if( p->mode==MODE_Explain ) p->mode = p->normalMode; 17387: p->autoExplain = 1; 17388: } 17389: }else 17390: 1.5 ! misho 17391: #ifndef SQLITE_OMIT_VIRTUALTABLE ! 17392: if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ ! 17393: open_db(p, 0); ! 17394: expertDotCommand(p, azArg, nArg); ! 17395: }else ! 17396: #endif ! 17397: ! 17398: if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){ ! 17399: static const struct { ! 17400: const char *zCtrlName; /* Name of a test-control option */ ! 17401: int ctrlCode; /* Integer code for that option */ ! 17402: const char *zUsage; /* Usage notes */ ! 17403: } aCtrl[] = { ! 17404: { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" }, ! 17405: { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" }, ! 17406: /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/ ! 17407: { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" }, ! 17408: { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" }, ! 17409: /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/ ! 17410: { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" }, ! 17411: { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" }, ! 17412: { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" }, ! 17413: { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" }, ! 17414: }; ! 17415: int filectrl = -1; ! 17416: int iCtrl = -1; ! 17417: sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */ ! 17418: int isOk = 0; /* 0: usage 1: %lld 2: no-result */ ! 17419: int n2, i; ! 17420: const char *zCmd = 0; ! 17421: const char *zSchema = 0; ! 17422: ! 17423: open_db(p, 0); ! 17424: zCmd = nArg>=2 ? azArg[1] : "help"; ! 17425: ! 17426: if( zCmd[0]=='-' ! 17427: && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0) ! 17428: && nArg>=4 ! 17429: ){ ! 17430: zSchema = azArg[2]; ! 17431: for(i=3; i<nArg; i++) azArg[i-2] = azArg[i]; ! 17432: nArg -= 2; ! 17433: zCmd = azArg[1]; ! 17434: } ! 17435: ! 17436: /* The argument can optionally begin with "-" or "--" */ ! 17437: if( zCmd[0]=='-' && zCmd[1] ){ ! 17438: zCmd++; ! 17439: if( zCmd[0]=='-' && zCmd[1] ) zCmd++; ! 17440: } ! 17441: ! 17442: /* --help lists all file-controls */ ! 17443: if( strcmp(zCmd,"help")==0 ){ ! 17444: utf8_printf(p->out, "Available file-controls:\n"); ! 17445: for(i=0; i<ArraySize(aCtrl); i++){ ! 17446: utf8_printf(p->out, " .filectrl %s %s\n", ! 17447: aCtrl[i].zCtrlName, aCtrl[i].zUsage); ! 17448: } ! 17449: rc = 1; ! 17450: goto meta_command_exit; ! 17451: } ! 17452: ! 17453: /* convert filectrl text option to value. allow any unique prefix ! 17454: ** of the option name, or a numerical value. */ ! 17455: n2 = strlen30(zCmd); ! 17456: for(i=0; i<ArraySize(aCtrl); i++){ ! 17457: if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){ ! 17458: if( filectrl<0 ){ ! 17459: filectrl = aCtrl[i].ctrlCode; ! 17460: iCtrl = i; ! 17461: }else{ ! 17462: utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n" ! 17463: "Use \".filectrl --help\" for help\n", zCmd); ! 17464: rc = 1; ! 17465: goto meta_command_exit; ! 17466: } ! 17467: } ! 17468: } ! 17469: if( filectrl<0 ){ ! 17470: utf8_printf(stderr,"Error: unknown file-control: %s\n" ! 17471: "Use \".filectrl --help\" for help\n", zCmd); ! 17472: }else{ ! 17473: switch(filectrl){ ! 17474: case SQLITE_FCNTL_SIZE_LIMIT: { ! 17475: if( nArg!=2 && nArg!=3 ) break; ! 17476: iRes = nArg==3 ? integerValue(azArg[2]) : -1; ! 17477: sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes); ! 17478: isOk = 1; ! 17479: break; ! 17480: } ! 17481: case SQLITE_FCNTL_LOCK_TIMEOUT: ! 17482: case SQLITE_FCNTL_CHUNK_SIZE: { ! 17483: int x; ! 17484: if( nArg!=3 ) break; ! 17485: x = (int)integerValue(azArg[2]); ! 17486: sqlite3_file_control(p->db, zSchema, filectrl, &x); ! 17487: isOk = 2; ! 17488: break; ! 17489: } ! 17490: case SQLITE_FCNTL_PERSIST_WAL: ! 17491: case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { ! 17492: int x; ! 17493: if( nArg!=2 && nArg!=3 ) break; ! 17494: x = nArg==3 ? booleanValue(azArg[2]) : -1; ! 17495: sqlite3_file_control(p->db, zSchema, filectrl, &x); ! 17496: iRes = x; ! 17497: isOk = 1; ! 17498: break; ! 17499: } ! 17500: case SQLITE_FCNTL_HAS_MOVED: { ! 17501: int x; ! 17502: if( nArg!=2 ) break; ! 17503: sqlite3_file_control(p->db, zSchema, filectrl, &x); ! 17504: iRes = x; ! 17505: isOk = 1; ! 17506: break; ! 17507: } ! 17508: case SQLITE_FCNTL_TEMPFILENAME: { ! 17509: char *z = 0; ! 17510: if( nArg!=2 ) break; ! 17511: sqlite3_file_control(p->db, zSchema, filectrl, &z); ! 17512: if( z ){ ! 17513: utf8_printf(p->out, "%s\n", z); ! 17514: sqlite3_free(z); ! 17515: } ! 17516: isOk = 2; ! 17517: break; ! 17518: } ! 17519: case SQLITE_FCNTL_RESERVE_BYTES: { ! 17520: int x; ! 17521: if( nArg>=3 ){ ! 17522: x = atoi(azArg[2]); ! 17523: sqlite3_file_control(p->db, zSchema, filectrl, &x); ! 17524: } ! 17525: x = -1; ! 17526: sqlite3_file_control(p->db, zSchema, filectrl, &x); ! 17527: utf8_printf(p->out,"%d\n", x); ! 17528: isOk = 2; ! 17529: break; ! 17530: } ! 17531: } ! 17532: } ! 17533: if( isOk==0 && iCtrl>=0 ){ ! 17534: utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); ! 17535: rc = 1; ! 17536: }else if( isOk==1 ){ ! 17537: char zBuf[100]; ! 17538: sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes); ! 17539: raw_printf(p->out, "%s\n", zBuf); ! 17540: } ! 17541: }else ! 17542: 1.4 misho 17543: if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ 17544: ShellState data; 17545: char *zErrMsg = 0; 17546: int doStats = 0; 17547: memcpy(&data, p, sizeof(data)); 17548: data.showHeader = 0; 17549: data.cMode = data.mode = MODE_Semi; 17550: if( nArg==2 && optionMatch(azArg[1], "indent") ){ 17551: data.cMode = data.mode = MODE_Pretty; 17552: nArg = 1; 17553: } 17554: if( nArg!=1 ){ 17555: raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); 17556: rc = 1; 17557: goto meta_command_exit; 17558: } 17559: open_db(p, 0); 17560: rc = sqlite3_exec(p->db, 17561: "SELECT sql FROM" 17562: " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" 1.5 ! misho 17563: " FROM sqlite_schema UNION ALL" ! 17564: " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " 1.4 misho 17565: "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " 17566: "ORDER BY rowid", 17567: callback, &data, &zErrMsg 17568: ); 17569: if( rc==SQLITE_OK ){ 17570: sqlite3_stmt *pStmt; 17571: rc = sqlite3_prepare_v2(p->db, 1.5 ! misho 17572: "SELECT rowid FROM sqlite_schema" 1.4 misho 17573: " WHERE name GLOB 'sqlite_stat[134]'", 17574: -1, &pStmt, 0); 17575: doStats = sqlite3_step(pStmt)==SQLITE_ROW; 17576: sqlite3_finalize(pStmt); 17577: } 17578: if( doStats==0 ){ 17579: raw_printf(p->out, "/* No STAT tables available */\n"); 17580: }else{ 1.5 ! misho 17581: raw_printf(p->out, "ANALYZE sqlite_schema;\n"); ! 17582: sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'", 1.4 misho 17583: callback, &data, &zErrMsg); 17584: data.cMode = data.mode = MODE_Insert; 17585: data.zDestTable = "sqlite_stat1"; 1.5 ! misho 17586: shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg); 1.4 misho 17587: data.zDestTable = "sqlite_stat4"; 1.5 ! misho 17588: shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg); ! 17589: raw_printf(p->out, "ANALYZE sqlite_schema;\n"); 1.2 misho 17590: } 17591: }else 17592: 1.4 misho 17593: if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){ 17594: if( nArg==2 ){ 17595: p->showHeader = booleanValue(azArg[1]); 1.5 ! misho 17596: p->shellFlgs |= SHFLG_HeaderSet; 1.4 misho 17597: }else{ 17598: raw_printf(stderr, "Usage: .headers on|off\n"); 17599: rc = 1; 17600: } 1.2 misho 17601: }else 17602: 1.5 ! misho 17603: if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ ! 17604: if( nArg>=2 ){ ! 17605: n = showHelp(p->out, azArg[1]); ! 17606: if( n==0 ){ ! 17607: utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); ! 17608: } ! 17609: }else{ ! 17610: showHelp(p->out, 0); ! 17611: } ! 17612: }else ! 17613: ! 17614: if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ ! 17615: char *zTable = 0; /* Insert data into this table */ ! 17616: char *zFile = 0; /* Name of file to extra content from */ ! 17617: sqlite3_stmt *pStmt = NULL; /* A statement */ ! 17618: int nCol; /* Number of columns in the table */ ! 17619: int nByte; /* Number of bytes in an SQL string */ ! 17620: int i, j; /* Loop counters */ ! 17621: int needCommit; /* True to COMMIT or ROLLBACK at end */ ! 17622: int nSep; /* Number of bytes in p->colSeparator[] */ ! 17623: char *zSql; /* An SQL statement */ ! 17624: ImportCtx sCtx; /* Reader context */ ! 17625: char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ ! 17626: int eVerbose = 0; /* Larger for more console output */ ! 17627: int nSkip = 0; /* Initial lines to skip */ ! 17628: int useOutputMode = 1; /* Use output mode to determine separators */ ! 17629: ! 17630: memset(&sCtx, 0, sizeof(sCtx)); ! 17631: if( p->mode==MODE_Ascii ){ ! 17632: xRead = ascii_read_one_field; ! 17633: }else{ ! 17634: xRead = csv_read_one_field; ! 17635: } ! 17636: for(i=1; i<nArg; i++){ ! 17637: char *z = azArg[i]; ! 17638: if( z[0]=='-' && z[1]=='-' ) z++; ! 17639: if( z[0]!='-' ){ ! 17640: if( zFile==0 ){ ! 17641: zFile = z; ! 17642: }else if( zTable==0 ){ ! 17643: zTable = z; ! 17644: }else{ ! 17645: utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z); ! 17646: showHelp(p->out, "import"); ! 17647: rc = 1; ! 17648: goto meta_command_exit; ! 17649: } ! 17650: }else if( strcmp(z,"-v")==0 ){ ! 17651: eVerbose++; ! 17652: }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){ ! 17653: nSkip = integerValue(azArg[++i]); ! 17654: }else if( strcmp(z,"-ascii")==0 ){ ! 17655: sCtx.cColSep = SEP_Unit[0]; ! 17656: sCtx.cRowSep = SEP_Record[0]; ! 17657: xRead = ascii_read_one_field; ! 17658: useOutputMode = 0; ! 17659: }else if( strcmp(z,"-csv")==0 ){ ! 17660: sCtx.cColSep = ','; ! 17661: sCtx.cRowSep = '\n'; ! 17662: xRead = csv_read_one_field; ! 17663: useOutputMode = 0; ! 17664: }else{ ! 17665: utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z); ! 17666: showHelp(p->out, "import"); ! 17667: rc = 1; ! 17668: goto meta_command_exit; ! 17669: } ! 17670: } ! 17671: if( zTable==0 ){ ! 17672: utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n", ! 17673: zFile==0 ? "FILE" : "TABLE"); ! 17674: showHelp(p->out, "import"); ! 17675: rc = 1; 1.4 misho 17676: goto meta_command_exit; 17677: } 17678: seenInterrupt = 0; 17679: open_db(p, 0); 1.5 ! misho 17680: if( useOutputMode ){ ! 17681: /* If neither the --csv or --ascii options are specified, then set ! 17682: ** the column and row separator characters from the output mode. */ ! 17683: nSep = strlen30(p->colSeparator); ! 17684: if( nSep==0 ){ ! 17685: raw_printf(stderr, ! 17686: "Error: non-null column separator required for import\n"); ! 17687: rc = 1; ! 17688: goto meta_command_exit; ! 17689: } ! 17690: if( nSep>1 ){ ! 17691: raw_printf(stderr, ! 17692: "Error: multi-character column separators not allowed" ! 17693: " for import\n"); ! 17694: rc = 1; ! 17695: goto meta_command_exit; ! 17696: } 1.4 misho 17697: nSep = strlen30(p->rowSeparator); 1.5 ! misho 17698: if( nSep==0 ){ ! 17699: raw_printf(stderr, ! 17700: "Error: non-null row separator required for import\n"); ! 17701: rc = 1; ! 17702: goto meta_command_exit; ! 17703: } ! 17704: if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){ ! 17705: /* When importing CSV (only), if the row separator is set to the ! 17706: ** default output row separator, change it to the default input ! 17707: ** row separator. This avoids having to maintain different input ! 17708: ** and output row separators. */ ! 17709: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); ! 17710: nSep = strlen30(p->rowSeparator); ! 17711: } ! 17712: if( nSep>1 ){ ! 17713: raw_printf(stderr, "Error: multi-character row separators not allowed" ! 17714: " for import\n"); ! 17715: rc = 1; ! 17716: goto meta_command_exit; ! 17717: } ! 17718: sCtx.cColSep = p->colSeparator[0]; ! 17719: sCtx.cRowSep = p->rowSeparator[0]; 1.4 misho 17720: } 17721: sCtx.zFile = zFile; 17722: sCtx.nLine = 1; 17723: if( sCtx.zFile[0]=='|' ){ 17724: #ifdef SQLITE_OMIT_POPEN 17725: raw_printf(stderr, "Error: pipes are not supported in this OS\n"); 1.5 ! misho 17726: rc = 1; ! 17727: goto meta_command_exit; 1.4 misho 17728: #else 17729: sCtx.in = popen(sCtx.zFile+1, "r"); 17730: sCtx.zFile = "<pipe>"; 1.5 ! misho 17731: sCtx.xCloser = pclose; 1.4 misho 17732: #endif 17733: }else{ 17734: sCtx.in = fopen(sCtx.zFile, "rb"); 1.5 ! misho 17735: sCtx.xCloser = fclose; 1.4 misho 17736: } 17737: if( sCtx.in==0 ){ 17738: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); 1.5 ! misho 17739: rc = 1; ! 17740: goto meta_command_exit; ! 17741: } ! 17742: if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ ! 17743: char zSep[2]; ! 17744: zSep[1] = 0; ! 17745: zSep[0] = sCtx.cColSep; ! 17746: utf8_printf(p->out, "Column separator "); ! 17747: output_c_string(p->out, zSep); ! 17748: utf8_printf(p->out, ", row separator "); ! 17749: zSep[0] = sCtx.cRowSep; ! 17750: output_c_string(p->out, zSep); ! 17751: utf8_printf(p->out, "\n"); ! 17752: } ! 17753: while( (nSkip--)>0 ){ ! 17754: while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} 1.4 misho 17755: } 1.2 misho 17756: zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); 17757: if( zSql==0 ){ 1.5 ! misho 17758: import_cleanup(&sCtx); ! 17759: shell_out_of_memory(); 1.2 misho 17760: } 17761: nByte = strlen30(zSql); 1.4 misho 17762: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); 17763: import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ 17764: if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ 17765: char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); 17766: char cSep = '('; 17767: while( xRead(&sCtx) ){ 17768: zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); 17769: cSep = ','; 17770: if( sCtx.cTerm!=sCtx.cColSep ) break; 17771: } 17772: if( cSep=='(' ){ 17773: sqlite3_free(zCreate); 1.5 ! misho 17774: import_cleanup(&sCtx); 1.4 misho 17775: utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); 1.5 ! misho 17776: rc = 1; ! 17777: goto meta_command_exit; 1.4 misho 17778: } 17779: zCreate = sqlite3_mprintf("%z\n)", zCreate); 1.5 ! misho 17780: if( eVerbose>=1 ){ ! 17781: utf8_printf(p->out, "%s\n", zCreate); ! 17782: } 1.4 misho 17783: rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); 17784: sqlite3_free(zCreate); 17785: if( rc ){ 17786: utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, 17787: sqlite3_errmsg(p->db)); 1.5 ! misho 17788: import_cleanup(&sCtx); ! 17789: rc = 1; ! 17790: goto meta_command_exit; 1.4 misho 17791: } 17792: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); 17793: } 1.2 misho 17794: sqlite3_free(zSql); 17795: if( rc ){ 17796: if (pStmt) sqlite3_finalize(pStmt); 1.4 misho 17797: utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); 1.5 ! misho 17798: import_cleanup(&sCtx); ! 17799: rc = 1; ! 17800: goto meta_command_exit; 1.2 misho 17801: } 17802: nCol = sqlite3_column_count(pStmt); 17803: sqlite3_finalize(pStmt); 17804: pStmt = 0; 17805: if( nCol==0 ) return 0; /* no columns, no error */ 1.4 misho 17806: zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); 1.2 misho 17807: if( zSql==0 ){ 1.5 ! misho 17808: import_cleanup(&sCtx); ! 17809: shell_out_of_memory(); 1.2 misho 17810: } 1.4 misho 17811: sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); 1.2 misho 17812: j = strlen30(zSql); 17813: for(i=1; i<nCol; i++){ 17814: zSql[j++] = ','; 17815: zSql[j++] = '?'; 17816: } 17817: zSql[j++] = ')'; 17818: zSql[j] = 0; 1.5 ! misho 17819: if( eVerbose>=2 ){ ! 17820: utf8_printf(p->out, "Insert using: %s\n", zSql); ! 17821: } 1.4 misho 17822: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); 17823: sqlite3_free(zSql); 1.2 misho 17824: if( rc ){ 1.4 misho 17825: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1.2 misho 17826: if (pStmt) sqlite3_finalize(pStmt); 1.5 ! misho 17827: import_cleanup(&sCtx); ! 17828: rc = 1; ! 17829: goto meta_command_exit; 1.2 misho 17830: } 1.4 misho 17831: needCommit = sqlite3_get_autocommit(p->db); 17832: if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); 17833: do{ 17834: int startLine = sCtx.nLine; 17835: for(i=0; i<nCol; i++){ 17836: char *z = xRead(&sCtx); 17837: /* 17838: ** Did we reach end-of-file before finding any columns? 17839: ** If so, stop instead of NULL filling the remaining columns. 17840: */ 17841: if( z==0 && i==0 ) break; 17842: /* 17843: ** Did we reach end-of-file OR end-of-line before finding any 17844: ** columns in ASCII mode? If so, stop instead of NULL filling 17845: ** the remaining columns. 17846: */ 17847: if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; 17848: sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); 17849: if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){ 17850: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - " 17851: "filling the rest with NULL\n", 17852: sCtx.zFile, startLine, nCol, i+1); 17853: i += 2; 17854: while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; } 17855: } 17856: } 17857: if( sCtx.cTerm==sCtx.cColSep ){ 17858: do{ 17859: xRead(&sCtx); 1.2 misho 17860: i++; 1.4 misho 17861: }while( sCtx.cTerm==sCtx.cColSep ); 17862: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - " 17863: "extras ignored\n", 17864: sCtx.zFile, startLine, nCol, i); 17865: } 17866: if( i>=nCol ){ 17867: sqlite3_step(pStmt); 17868: rc = sqlite3_reset(pStmt); 17869: if( rc!=SQLITE_OK ){ 17870: utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, 17871: startLine, sqlite3_errmsg(p->db)); 1.5 ! misho 17872: sCtx.nErr++; ! 17873: }else{ ! 17874: sCtx.nRow++; 1.2 misho 17875: } 17876: } 1.4 misho 17877: }while( sCtx.cTerm!=EOF ); 17878: 1.5 ! misho 17879: import_cleanup(&sCtx); 1.2 misho 17880: sqlite3_finalize(pStmt); 1.4 misho 17881: if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); 1.5 ! misho 17882: if( eVerbose>0 ){ ! 17883: utf8_printf(p->out, ! 17884: "Added %d rows with %d errors using %d lines of input\n", ! 17885: sCtx.nRow, sCtx.nErr, sCtx.nLine-1); ! 17886: } 1.2 misho 17887: }else 17888: 1.5 ! misho 17889: #ifndef SQLITE_UNTESTABLE ! 17890: if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ ! 17891: char *zSql; ! 17892: char *zCollist = 0; ! 17893: sqlite3_stmt *pStmt; ! 17894: int tnum = 0; ! 17895: int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ ! 17896: int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ ! 17897: int i; ! 17898: if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ ! 17899: utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" ! 17900: " .imposter off\n"); ! 17901: /* Also allowed, but not documented: ! 17902: ** ! 17903: ** .imposter TABLE IMPOSTER ! 17904: ** ! 17905: ** where TABLE is a WITHOUT ROWID table. In that case, the ! 17906: ** imposter is another WITHOUT ROWID table with the columns in ! 17907: ** storage order. */ ! 17908: rc = 1; ! 17909: goto meta_command_exit; ! 17910: } 1.4 misho 17911: open_db(p, 0); 1.5 ! misho 17912: if( nArg==2 ){ ! 17913: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); ! 17914: goto meta_command_exit; ! 17915: } ! 17916: zSql = sqlite3_mprintf( ! 17917: "SELECT rootpage, 0 FROM sqlite_schema" ! 17918: " WHERE name='%q' AND type='index'" ! 17919: "UNION ALL " ! 17920: "SELECT rootpage, 1 FROM sqlite_schema" ! 17921: " WHERE name='%q' AND type='table'" ! 17922: " AND sql LIKE '%%without%%rowid%%'", ! 17923: azArg[1], azArg[1] ! 17924: ); ! 17925: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 17926: sqlite3_free(zSql); ! 17927: if( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 17928: tnum = sqlite3_column_int(pStmt, 0); ! 17929: isWO = sqlite3_column_int(pStmt, 1); ! 17930: } ! 17931: sqlite3_finalize(pStmt); ! 17932: zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); ! 17933: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 17934: sqlite3_free(zSql); ! 17935: i = 0; ! 17936: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 17937: char zLabel[20]; ! 17938: const char *zCol = (const char*)sqlite3_column_text(pStmt,2); ! 17939: i++; ! 17940: if( zCol==0 ){ ! 17941: if( sqlite3_column_int(pStmt,1)==-1 ){ ! 17942: zCol = "_ROWID_"; ! 17943: }else{ ! 17944: sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); ! 17945: zCol = zLabel; ! 17946: } ! 17947: } ! 17948: if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ ! 17949: lenPK = (int)strlen(zCollist); ! 17950: } ! 17951: if( zCollist==0 ){ ! 17952: zCollist = sqlite3_mprintf("\"%w\"", zCol); ! 17953: }else{ ! 17954: zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); ! 17955: } ! 17956: } ! 17957: sqlite3_finalize(pStmt); ! 17958: if( i==0 || tnum==0 ){ ! 17959: utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); 1.4 misho 17960: rc = 1; 1.5 ! misho 17961: sqlite3_free(zCollist); 1.4 misho 17962: goto meta_command_exit; 1.2 misho 17963: } 1.5 ! misho 17964: if( lenPK==0 ) lenPK = 100000; ! 17965: zSql = sqlite3_mprintf( ! 17966: "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", ! 17967: azArg[2], zCollist, lenPK, zCollist); ! 17968: sqlite3_free(zCollist); ! 17969: rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); ! 17970: if( rc==SQLITE_OK ){ ! 17971: rc = sqlite3_exec(p->db, zSql, 0, 0, 0); ! 17972: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); ! 17973: if( rc ){ ! 17974: utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); ! 17975: }else{ ! 17976: utf8_printf(stdout, "%s;\n", zSql); ! 17977: raw_printf(stdout, ! 17978: "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", ! 17979: azArg[1], isWO ? "table" : "index" ! 17980: ); ! 17981: } ! 17982: }else{ ! 17983: raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); 1.2 misho 17984: rc = 1; 17985: } 1.5 ! misho 17986: sqlite3_free(zSql); 1.2 misho 17987: }else 1.5 ! misho 17988: #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */ 1.2 misho 17989: 17990: #ifdef SQLITE_ENABLE_IOTRACE 17991: if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ 1.4 misho 17992: SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); 1.2 misho 17993: if( iotrace && iotrace!=stdout ) fclose(iotrace); 17994: iotrace = 0; 17995: if( nArg<2 ){ 17996: sqlite3IoTrace = 0; 17997: }else if( strcmp(azArg[1], "-")==0 ){ 17998: sqlite3IoTrace = iotracePrintf; 17999: iotrace = stdout; 1.4 misho 18000: }else{ 18001: iotrace = fopen(azArg[1], "w"); 18002: if( iotrace==0 ){ 18003: utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); 18004: sqlite3IoTrace = 0; 18005: rc = 1; 18006: }else{ 18007: sqlite3IoTrace = iotracePrintf; 18008: } 18009: } 18010: }else 18011: #endif 1.5 ! misho 18012: 1.4 misho 18013: if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ 18014: static const struct { 18015: const char *zLimitName; /* Name of a limit */ 18016: int limitCode; /* Integer code for that limit */ 18017: } aLimit[] = { 18018: { "length", SQLITE_LIMIT_LENGTH }, 18019: { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, 18020: { "column", SQLITE_LIMIT_COLUMN }, 18021: { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, 18022: { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, 18023: { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, 18024: { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, 18025: { "attached", SQLITE_LIMIT_ATTACHED }, 18026: { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, 18027: { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, 18028: { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, 18029: { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, 18030: }; 18031: int i, n2; 18032: open_db(p, 0); 18033: if( nArg==1 ){ 18034: for(i=0; i<ArraySize(aLimit); i++){ 18035: printf("%20s %d\n", aLimit[i].zLimitName, 18036: sqlite3_limit(p->db, aLimit[i].limitCode, -1)); 18037: } 18038: }else if( nArg>3 ){ 18039: raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); 18040: rc = 1; 18041: goto meta_command_exit; 18042: }else{ 18043: int iLimit = -1; 18044: n2 = strlen30(azArg[1]); 18045: for(i=0; i<ArraySize(aLimit); i++){ 18046: if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){ 18047: if( iLimit<0 ){ 18048: iLimit = i; 18049: }else{ 18050: utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]); 18051: rc = 1; 18052: goto meta_command_exit; 18053: } 18054: } 18055: } 18056: if( iLimit<0 ){ 18057: utf8_printf(stderr, "unknown limit: \"%s\"\n" 18058: "enter \".limits\" with no arguments for a list.\n", 18059: azArg[1]); 1.2 misho 18060: rc = 1; 1.4 misho 18061: goto meta_command_exit; 18062: } 18063: if( nArg==3 ){ 18064: sqlite3_limit(p->db, aLimit[iLimit].limitCode, 18065: (int)integerValue(azArg[2])); 1.2 misho 18066: } 1.4 misho 18067: printf("%20s %d\n", aLimit[iLimit].zLimitName, 18068: sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); 1.2 misho 18069: } 18070: }else 18071: 1.5 ! misho 18072: if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){ ! 18073: open_db(p, 0); ! 18074: lintDotCommand(p, azArg, nArg); ! 18075: }else ! 18076: 1.2 misho 18077: #ifndef SQLITE_OMIT_LOAD_EXTENSION 1.4 misho 18078: if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ 1.2 misho 18079: const char *zFile, *zProc; 18080: char *zErrMsg = 0; 1.4 misho 18081: if( nArg<2 ){ 18082: raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); 18083: rc = 1; 18084: goto meta_command_exit; 18085: } 1.2 misho 18086: zFile = azArg[1]; 18087: zProc = nArg>=3 ? azArg[2] : 0; 1.4 misho 18088: open_db(p, 0); 1.2 misho 18089: rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); 18090: if( rc!=SQLITE_OK ){ 1.4 misho 18091: utf8_printf(stderr, "Error: %s\n", zErrMsg); 1.2 misho 18092: sqlite3_free(zErrMsg); 18093: rc = 1; 18094: } 18095: }else 18096: #endif 18097: 1.4 misho 18098: if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ 18099: if( nArg!=2 ){ 18100: raw_printf(stderr, "Usage: .log FILENAME\n"); 18101: rc = 1; 18102: }else{ 18103: const char *zFile = azArg[1]; 18104: output_file_close(p->pLog); 1.5 ! misho 18105: p->pLog = output_file_open(zFile, 0); 1.4 misho 18106: } 1.2 misho 18107: }else 18108: 1.4 misho 18109: if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ 18110: const char *zMode = nArg>=2 ? azArg[1] : ""; 1.5 ! misho 18111: int n2 = strlen30(zMode); 1.4 misho 18112: int c2 = zMode[0]; 18113: if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ 1.2 misho 18114: p->mode = MODE_Line; 1.5 ! misho 18115: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); 1.4 misho 18116: }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ 1.2 misho 18117: p->mode = MODE_Column; 1.5 ! misho 18118: if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ ! 18119: p->showHeader = 1; ! 18120: } ! 18121: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); 1.4 misho 18122: }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ 1.2 misho 18123: p->mode = MODE_List; 1.5 ! misho 18124: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); ! 18125: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); 1.4 misho 18126: }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ 1.2 misho 18127: p->mode = MODE_Html; 1.4 misho 18128: }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ 1.2 misho 18129: p->mode = MODE_Tcl; 1.4 misho 18130: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); 1.5 ! misho 18131: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); 1.4 misho 18132: }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ 1.2 misho 18133: p->mode = MODE_Csv; 1.4 misho 18134: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); 18135: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); 18136: }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ 1.2 misho 18137: p->mode = MODE_List; 1.4 misho 18138: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); 18139: }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ 1.2 misho 18140: p->mode = MODE_Insert; 1.4 misho 18141: set_table_name(p, nArg>=3 ? azArg[2] : "table"); 1.5 ! misho 18142: }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ ! 18143: p->mode = MODE_Quote; ! 18144: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); ! 18145: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); 1.4 misho 18146: }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ 18147: p->mode = MODE_Ascii; 18148: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); 18149: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); 1.5 ! misho 18150: }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){ ! 18151: p->mode = MODE_Markdown; ! 18152: }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){ ! 18153: p->mode = MODE_Table; ! 18154: }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){ ! 18155: p->mode = MODE_Box; ! 18156: }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){ ! 18157: p->mode = MODE_Json; ! 18158: }else if( nArg==1 ){ ! 18159: raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); ! 18160: }else{ 1.4 misho 18161: raw_printf(stderr, "Error: mode should be one of: " 1.5 ! misho 18162: "ascii box column csv html insert json line list markdown " ! 18163: "quote table tabs tcl\n"); 1.2 misho 18164: rc = 1; 18165: } 1.4 misho 18166: p->cMode = p->mode; 1.2 misho 18167: }else 18168: 1.4 misho 18169: if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ 18170: if( nArg==2 ){ 18171: sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, 18172: "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); 18173: }else{ 18174: raw_printf(stderr, "Usage: .nullvalue STRING\n"); 1.2 misho 18175: rc = 1; 18176: } 18177: }else 18178: 1.5 ! misho 18179: #ifdef SQLITE_DEBUG ! 18180: if( c=='o' && strcmp(azArg[0],"oom")==0 ){ ! 18181: int i; ! 18182: for(i=1; i<nArg; i++){ ! 18183: const char *z = azArg[i]; ! 18184: if( z[0]=='-' && z[1]=='-' ) z++; ! 18185: if( strcmp(z,"-repeat")==0 ){ ! 18186: if( i==nArg-1 ){ ! 18187: raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]); ! 18188: rc = 1; ! 18189: }else{ ! 18190: oomRepeat = (int)integerValue(azArg[++i]); ! 18191: } ! 18192: }else if( IsDigit(z[0]) ){ ! 18193: oomCounter = (int)integerValue(azArg[i]); ! 18194: }else{ ! 18195: raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]); ! 18196: raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n"); ! 18197: rc = 1; ! 18198: } ! 18199: } ! 18200: if( rc==0 ){ ! 18201: raw_printf(p->out, "oomCounter = %d\n", oomCounter); ! 18202: raw_printf(p->out, "oomRepeat = %d\n", oomRepeat); ! 18203: } ! 18204: }else ! 18205: #endif /* SQLITE_DEBUG */ ! 18206: 1.4 misho 18207: if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ 1.5 ! misho 18208: char *zNewFilename; /* Name of the database file to open */ ! 18209: int iName = 1; /* Index in azArg[] of the filename */ ! 18210: int newFlag = 0; /* True to delete file before opening */ ! 18211: /* Close the existing database */ ! 18212: session_close_all(p); ! 18213: close_db(p->db); 1.4 misho 18214: p->db = 0; 1.5 ! misho 18215: p->zDbFilename = 0; ! 18216: sqlite3_free(p->zFreeOnClose); ! 18217: p->zFreeOnClose = 0; ! 18218: p->openMode = SHELL_OPEN_UNSPEC; ! 18219: p->openFlags = 0; ! 18220: p->szMax = 0; ! 18221: /* Check for command-line arguments */ ! 18222: for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ ! 18223: const char *z = azArg[iName]; ! 18224: if( optionMatch(z,"new") ){ ! 18225: newFlag = 1; ! 18226: #ifdef SQLITE_HAVE_ZLIB ! 18227: }else if( optionMatch(z, "zip") ){ ! 18228: p->openMode = SHELL_OPEN_ZIPFILE; ! 18229: #endif ! 18230: }else if( optionMatch(z, "append") ){ ! 18231: p->openMode = SHELL_OPEN_APPENDVFS; ! 18232: }else if( optionMatch(z, "readonly") ){ ! 18233: p->openMode = SHELL_OPEN_READONLY; ! 18234: }else if( optionMatch(z, "nofollow") ){ ! 18235: p->openFlags |= SQLITE_OPEN_NOFOLLOW; ! 18236: #ifdef SQLITE_ENABLE_DESERIALIZE ! 18237: }else if( optionMatch(z, "deserialize") ){ ! 18238: p->openMode = SHELL_OPEN_DESERIALIZE; ! 18239: }else if( optionMatch(z, "hexdb") ){ ! 18240: p->openMode = SHELL_OPEN_HEXDB; ! 18241: }else if( optionMatch(z, "maxsize") && iName+1<nArg ){ ! 18242: p->szMax = integerValue(azArg[++iName]); ! 18243: #endif /* SQLITE_ENABLE_DESERIALIZE */ ! 18244: }else if( z[0]=='-' ){ ! 18245: utf8_printf(stderr, "unknown option: %s\n", z); ! 18246: rc = 1; ! 18247: goto meta_command_exit; ! 18248: } ! 18249: } ! 18250: /* If a filename is specified, try to open it first */ ! 18251: zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0; ! 18252: if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ ! 18253: if( newFlag ) shellDeleteFile(zNewFilename); ! 18254: p->zDbFilename = zNewFilename; ! 18255: open_db(p, OPEN_DB_KEEPALIVE); ! 18256: if( p->db==0 ){ ! 18257: utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); ! 18258: sqlite3_free(zNewFilename); ! 18259: }else{ ! 18260: p->zFreeOnClose = zNewFilename; ! 18261: } ! 18262: } ! 18263: if( p->db==0 ){ ! 18264: /* As a fall-back open a TEMP database */ ! 18265: p->zDbFilename = 0; ! 18266: open_db(p, 0); 1.4 misho 18267: } 1.2 misho 18268: }else 18269: 1.5 ! misho 18270: if( (c=='o' ! 18271: && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) ! 18272: || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) 1.4 misho 18273: ){ 1.5 ! misho 18274: const char *zFile = 0; ! 18275: int bTxtMode = 0; ! 18276: int i; ! 18277: int eMode = 0; ! 18278: int bBOM = 0; ! 18279: int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */ ! 18280: ! 18281: if( c=='e' ){ ! 18282: eMode = 'x'; ! 18283: bOnce = 2; ! 18284: }else if( strncmp(azArg[0],"once",n)==0 ){ ! 18285: bOnce = 1; 1.4 misho 18286: } 1.5 ! misho 18287: for(i=1; i<nArg; i++){ ! 18288: char *z = azArg[i]; ! 18289: if( z[0]=='-' ){ ! 18290: if( z[1]=='-' ) z++; ! 18291: if( strcmp(z,"-bom")==0 ){ ! 18292: bBOM = 1; ! 18293: }else if( c!='e' && strcmp(z,"-x")==0 ){ ! 18294: eMode = 'x'; /* spreadsheet */ ! 18295: }else if( c!='e' && strcmp(z,"-e")==0 ){ ! 18296: eMode = 'e'; /* text editor */ ! 18297: }else{ ! 18298: utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", ! 18299: azArg[i]); ! 18300: showHelp(p->out, azArg[0]); ! 18301: rc = 1; ! 18302: goto meta_command_exit; ! 18303: } ! 18304: }else if( zFile==0 ){ ! 18305: zFile = z; ! 18306: }else{ ! 18307: utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n", ! 18308: azArg[i]); ! 18309: showHelp(p->out, azArg[0]); 1.4 misho 18310: rc = 1; 18311: goto meta_command_exit; 18312: } 1.5 ! misho 18313: } ! 18314: if( zFile==0 ) zFile = "stdout"; ! 18315: if( bOnce ){ 1.4 misho 18316: p->outCount = 2; 1.3 misho 18317: }else{ 1.4 misho 18318: p->outCount = 0; 1.2 misho 18319: } 1.4 misho 18320: output_reset(p); 1.5 ! misho 18321: #ifndef SQLITE_NOHAVE_SYSTEM ! 18322: if( eMode=='e' || eMode=='x' ){ ! 18323: p->doXdgOpen = 1; ! 18324: outputModePush(p); ! 18325: if( eMode=='x' ){ ! 18326: /* spreadsheet mode. Output as CSV. */ ! 18327: newTempFile(p, "csv"); ! 18328: ShellClearFlag(p, SHFLG_Echo); ! 18329: p->mode = MODE_Csv; ! 18330: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); ! 18331: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); ! 18332: }else{ ! 18333: /* text editor mode */ ! 18334: newTempFile(p, "txt"); ! 18335: bTxtMode = 1; ! 18336: } ! 18337: zFile = p->zTempFile; ! 18338: } ! 18339: #endif /* SQLITE_NOHAVE_SYSTEM */ 1.4 misho 18340: if( zFile[0]=='|' ){ 18341: #ifdef SQLITE_OMIT_POPEN 18342: raw_printf(stderr, "Error: pipes are not supported in this OS\n"); 18343: rc = 1; 18344: p->out = stdout; 18345: #else 18346: p->out = popen(zFile + 1, "w"); 1.3 misho 18347: if( p->out==0 ){ 1.4 misho 18348: utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); 1.3 misho 18349: p->out = stdout; 18350: rc = 1; 18351: }else{ 1.5 ! misho 18352: if( bBOM ) fprintf(p->out,"\357\273\277"); 1.4 misho 18353: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); 1.3 misho 18354: } 1.4 misho 18355: #endif 1.2 misho 18356: }else{ 1.5 ! misho 18357: p->out = output_file_open(zFile, bTxtMode); 1.2 misho 18358: if( p->out==0 ){ 1.4 misho 18359: if( strcmp(zFile,"off")!=0 ){ 18360: utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); 1.3 misho 18361: } 1.2 misho 18362: p->out = stdout; 18363: rc = 1; 18364: } else { 1.5 ! misho 18365: if( bBOM ) fprintf(p->out,"\357\273\277"); 1.4 misho 18366: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); 1.2 misho 18367: } 18368: } 18369: }else 18370: 1.5 ! misho 18371: if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){ ! 18372: open_db(p,0); ! 18373: if( nArg<=1 ) goto parameter_syntax_error; ! 18374: ! 18375: /* .parameter clear ! 18376: ** Clear all bind parameters by dropping the TEMP table that holds them. ! 18377: */ ! 18378: if( nArg==2 && strcmp(azArg[1],"clear")==0 ){ ! 18379: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;", ! 18380: 0, 0, 0); ! 18381: }else ! 18382: ! 18383: /* .parameter list ! 18384: ** List all bind parameters. ! 18385: */ ! 18386: if( nArg==2 && strcmp(azArg[1],"list")==0 ){ ! 18387: sqlite3_stmt *pStmt = 0; ! 18388: int rx; ! 18389: int len = 0; ! 18390: rx = sqlite3_prepare_v2(p->db, ! 18391: "SELECT max(length(key)) " ! 18392: "FROM temp.sqlite_parameters;", -1, &pStmt, 0); ! 18393: if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ ! 18394: len = sqlite3_column_int(pStmt, 0); ! 18395: if( len>40 ) len = 40; ! 18396: } ! 18397: sqlite3_finalize(pStmt); ! 18398: pStmt = 0; ! 18399: if( len ){ ! 18400: rx = sqlite3_prepare_v2(p->db, ! 18401: "SELECT key, quote(value) " ! 18402: "FROM temp.sqlite_parameters;", -1, &pStmt, 0); ! 18403: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 18404: utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), ! 18405: sqlite3_column_text(pStmt,1)); ! 18406: } ! 18407: sqlite3_finalize(pStmt); ! 18408: } ! 18409: }else ! 18410: ! 18411: /* .parameter init ! 18412: ** Make sure the TEMP table used to hold bind parameters exists. ! 18413: ** Create it if necessary. ! 18414: */ ! 18415: if( nArg==2 && strcmp(azArg[1],"init")==0 ){ ! 18416: bind_table_init(p); ! 18417: }else ! 18418: ! 18419: /* .parameter set NAME VALUE ! 18420: ** Set or reset a bind parameter. NAME should be the full parameter ! 18421: ** name exactly as it appears in the query. (ex: $abc, @def). The ! 18422: ** VALUE can be in either SQL literal notation, or if not it will be ! 18423: ** understood to be a text string. ! 18424: */ ! 18425: if( nArg==4 && strcmp(azArg[1],"set")==0 ){ ! 18426: int rx; ! 18427: char *zSql; ! 18428: sqlite3_stmt *pStmt; ! 18429: const char *zKey = azArg[2]; ! 18430: const char *zValue = azArg[3]; ! 18431: bind_table_init(p); ! 18432: zSql = sqlite3_mprintf( ! 18433: "REPLACE INTO temp.sqlite_parameters(key,value)" ! 18434: "VALUES(%Q,%s);", zKey, zValue); ! 18435: if( zSql==0 ) shell_out_of_memory(); ! 18436: pStmt = 0; ! 18437: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 18438: sqlite3_free(zSql); ! 18439: if( rx!=SQLITE_OK ){ ! 18440: sqlite3_finalize(pStmt); ! 18441: pStmt = 0; ! 18442: zSql = sqlite3_mprintf( ! 18443: "REPLACE INTO temp.sqlite_parameters(key,value)" ! 18444: "VALUES(%Q,%Q);", zKey, zValue); ! 18445: if( zSql==0 ) shell_out_of_memory(); ! 18446: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 18447: sqlite3_free(zSql); ! 18448: if( rx!=SQLITE_OK ){ ! 18449: utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db)); ! 18450: sqlite3_finalize(pStmt); ! 18451: pStmt = 0; ! 18452: rc = 1; ! 18453: } ! 18454: } ! 18455: sqlite3_step(pStmt); ! 18456: sqlite3_finalize(pStmt); ! 18457: }else ! 18458: ! 18459: /* .parameter unset NAME ! 18460: ** Remove the NAME binding from the parameter binding table, if it ! 18461: ** exists. ! 18462: */ ! 18463: if( nArg==3 && strcmp(azArg[1],"unset")==0 ){ ! 18464: char *zSql = sqlite3_mprintf( ! 18465: "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]); ! 18466: if( zSql==0 ) shell_out_of_memory(); ! 18467: sqlite3_exec(p->db, zSql, 0, 0, 0); ! 18468: sqlite3_free(zSql); ! 18469: }else ! 18470: /* If no command name matches, show a syntax error */ ! 18471: parameter_syntax_error: ! 18472: showHelp(p->out, "parameter"); ! 18473: }else ! 18474: 1.3 misho 18475: if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ 18476: int i; 18477: for(i=1; i<nArg; i++){ 1.4 misho 18478: if( i>1 ) raw_printf(p->out, " "); 18479: utf8_printf(p->out, "%s", azArg[i]); 1.3 misho 18480: } 1.4 misho 18481: raw_printf(p->out, "\n"); 1.3 misho 18482: }else 18483: 1.5 ! misho 18484: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK ! 18485: if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){ ! 18486: int i; ! 18487: int nn = 0; ! 18488: p->flgProgress = 0; ! 18489: p->mxProgress = 0; ! 18490: p->nProgress = 0; ! 18491: for(i=1; i<nArg; i++){ ! 18492: const char *z = azArg[i]; ! 18493: if( z[0]=='-' ){ ! 18494: z++; ! 18495: if( z[0]=='-' ) z++; ! 18496: if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){ ! 18497: p->flgProgress |= SHELL_PROGRESS_QUIET; ! 18498: continue; ! 18499: } ! 18500: if( strcmp(z,"reset")==0 ){ ! 18501: p->flgProgress |= SHELL_PROGRESS_RESET; ! 18502: continue; ! 18503: } ! 18504: if( strcmp(z,"once")==0 ){ ! 18505: p->flgProgress |= SHELL_PROGRESS_ONCE; ! 18506: continue; ! 18507: } ! 18508: if( strcmp(z,"limit")==0 ){ ! 18509: if( i+1>=nArg ){ ! 18510: utf8_printf(stderr, "Error: missing argument on --limit\n"); ! 18511: rc = 1; ! 18512: goto meta_command_exit; ! 18513: }else{ ! 18514: p->mxProgress = (int)integerValue(azArg[++i]); ! 18515: } ! 18516: continue; ! 18517: } ! 18518: utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]); ! 18519: rc = 1; ! 18520: goto meta_command_exit; ! 18521: }else{ ! 18522: nn = (int)integerValue(z); ! 18523: } ! 18524: } ! 18525: open_db(p, 0); ! 18526: sqlite3_progress_handler(p->db, nn, progress_handler, p); ! 18527: }else ! 18528: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ ! 18529: 1.4 misho 18530: if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){ 1.2 misho 18531: if( nArg >= 2) { 18532: strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); 18533: } 18534: if( nArg >= 3) { 18535: strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); 18536: } 18537: }else 18538: 1.4 misho 18539: if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ 1.2 misho 18540: rc = 2; 18541: }else 18542: 1.4 misho 18543: if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){ 1.5 ! misho 18544: FILE *inSaved = p->in; ! 18545: int savedLineno = p->lineno; 1.4 misho 18546: if( nArg!=2 ){ 18547: raw_printf(stderr, "Usage: .read FILE\n"); 18548: rc = 1; 18549: goto meta_command_exit; 18550: } 1.5 ! misho 18551: if( notNormalFile(azArg[1]) ! 18552: || (p->in = fopen(azArg[1], "rb"))==0 ! 18553: ){ 1.4 misho 18554: utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); 1.2 misho 18555: rc = 1; 18556: }else{ 1.5 ! misho 18557: rc = process_input(p); ! 18558: fclose(p->in); 1.2 misho 18559: } 1.5 ! misho 18560: p->in = inSaved; ! 18561: p->lineno = savedLineno; 1.2 misho 18562: }else 18563: 1.4 misho 18564: if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){ 1.2 misho 18565: const char *zSrcFile; 18566: const char *zDb; 18567: sqlite3 *pSrc; 18568: sqlite3_backup *pBackup; 18569: int nTimeout = 0; 18570: 18571: if( nArg==2 ){ 18572: zSrcFile = azArg[1]; 18573: zDb = "main"; 1.4 misho 18574: }else if( nArg==3 ){ 1.2 misho 18575: zSrcFile = azArg[2]; 18576: zDb = azArg[1]; 1.4 misho 18577: }else{ 18578: raw_printf(stderr, "Usage: .restore ?DB? FILE\n"); 18579: rc = 1; 18580: goto meta_command_exit; 1.2 misho 18581: } 18582: rc = sqlite3_open(zSrcFile, &pSrc); 18583: if( rc!=SQLITE_OK ){ 1.4 misho 18584: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); 1.5 ! misho 18585: close_db(pSrc); 1.2 misho 18586: return 1; 18587: } 1.4 misho 18588: open_db(p, 0); 1.2 misho 18589: pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); 18590: if( pBackup==0 ){ 1.4 misho 18591: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1.5 ! misho 18592: close_db(pSrc); 1.2 misho 18593: return 1; 18594: } 18595: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK 18596: || rc==SQLITE_BUSY ){ 18597: if( rc==SQLITE_BUSY ){ 18598: if( nTimeout++ >= 3 ) break; 18599: sqlite3_sleep(100); 18600: } 18601: } 18602: sqlite3_backup_finish(pBackup); 18603: if( rc==SQLITE_DONE ){ 18604: rc = 0; 18605: }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ 1.4 misho 18606: raw_printf(stderr, "Error: source database is busy\n"); 1.2 misho 18607: rc = 1; 18608: }else{ 1.4 misho 18609: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); 1.2 misho 18610: rc = 1; 18611: } 1.5 ! misho 18612: close_db(pSrc); 1.2 misho 18613: }else 18614: 1.4 misho 18615: if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ 18616: if( nArg==2 ){ 1.5 ! misho 18617: p->scanstatsOn = (u8)booleanValue(azArg[1]); 1.4 misho 18618: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS 18619: raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); 18620: #endif 18621: }else{ 18622: raw_printf(stderr, "Usage: .scanstats on|off\n"); 18623: rc = 1; 18624: } 18625: }else 18626: 18627: if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ 1.5 ! misho 18628: ShellText sSelect; 1.4 misho 18629: ShellState data; 1.2 misho 18630: char *zErrMsg = 0; 1.5 ! misho 18631: const char *zDiv = "("; ! 18632: const char *zName = 0; ! 18633: int iSchema = 0; ! 18634: int bDebug = 0; ! 18635: int ii; ! 18636: 1.4 misho 18637: open_db(p, 0); 1.2 misho 18638: memcpy(&data, p, sizeof(data)); 18639: data.showHeader = 0; 1.4 misho 18640: data.cMode = data.mode = MODE_Semi; 1.5 ! misho 18641: initText(&sSelect); ! 18642: for(ii=1; ii<nArg; ii++){ ! 18643: if( optionMatch(azArg[ii],"indent") ){ ! 18644: data.cMode = data.mode = MODE_Pretty; ! 18645: }else if( optionMatch(azArg[ii],"debug") ){ ! 18646: bDebug = 1; ! 18647: }else if( zName==0 ){ ! 18648: zName = azArg[ii]; ! 18649: }else{ ! 18650: raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); ! 18651: rc = 1; ! 18652: goto meta_command_exit; ! 18653: } 1.4 misho 18654: } 1.5 ! misho 18655: if( zName!=0 ){ ! 18656: int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0 ! 18657: || sqlite3_strlike(zName, "sqlite_schema", '\\')==0 ! 18658: || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ! 18659: || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0; ! 18660: if( isSchema ){ 1.2 misho 18661: char *new_argv[2], *new_colv[2]; 1.5 ! misho 18662: new_argv[0] = sqlite3_mprintf( ! 18663: "CREATE TABLE %s (\n" 1.2 misho 18664: " type text,\n" 18665: " name text,\n" 18666: " tbl_name text,\n" 18667: " rootpage integer,\n" 18668: " sql text\n" 1.5 ! misho 18669: ")", zName); 1.2 misho 18670: new_argv[1] = 0; 18671: new_colv[0] = "sql"; 18672: new_colv[1] = 0; 18673: callback(&data, 1, new_argv, new_colv); 1.5 ! misho 18674: sqlite3_free(new_argv[0]); ! 18675: } ! 18676: } ! 18677: if( zDiv ){ ! 18678: sqlite3_stmt *pStmt = 0; ! 18679: rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list", ! 18680: -1, &pStmt, 0); ! 18681: if( rc ){ ! 18682: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); ! 18683: sqlite3_finalize(pStmt); ! 18684: rc = 1; ! 18685: goto meta_command_exit; ! 18686: } ! 18687: appendText(&sSelect, "SELECT sql FROM", 0); ! 18688: iSchema = 0; ! 18689: while( sqlite3_step(pStmt)==SQLITE_ROW ){ ! 18690: const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); ! 18691: char zScNum[30]; ! 18692: sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); ! 18693: appendText(&sSelect, zDiv, 0); ! 18694: zDiv = " UNION ALL "; ! 18695: appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); ! 18696: if( sqlite3_stricmp(zDb, "main")!=0 ){ ! 18697: appendText(&sSelect, zDb, '\''); ! 18698: }else{ ! 18699: appendText(&sSelect, "NULL", 0); ! 18700: } ! 18701: appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0); ! 18702: appendText(&sSelect, zScNum, 0); ! 18703: appendText(&sSelect, " AS snum, ", 0); ! 18704: appendText(&sSelect, zDb, '\''); ! 18705: appendText(&sSelect, " AS sname FROM ", 0); ! 18706: appendText(&sSelect, zDb, quoteChar(zDb)); ! 18707: appendText(&sSelect, ".sqlite_schema", 0); ! 18708: } ! 18709: sqlite3_finalize(pStmt); ! 18710: #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS ! 18711: if( zName ){ ! 18712: appendText(&sSelect, ! 18713: " UNION ALL SELECT shell_module_schema(name)," ! 18714: " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", ! 18715: 0); ! 18716: } ! 18717: #endif ! 18718: appendText(&sSelect, ") WHERE ", 0); ! 18719: if( zName ){ ! 18720: char *zQarg = sqlite3_mprintf("%Q", zName); ! 18721: int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || ! 18722: strchr(zName, '[') != 0; ! 18723: if( strchr(zName, '.') ){ ! 18724: appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); ! 18725: }else{ ! 18726: appendText(&sSelect, "lower(tbl_name)", 0); ! 18727: } ! 18728: appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0); ! 18729: appendText(&sSelect, zQarg, 0); ! 18730: if( !bGlob ){ ! 18731: appendText(&sSelect, " ESCAPE '\\' ", 0); ! 18732: } ! 18733: appendText(&sSelect, " AND ", 0); ! 18734: sqlite3_free(zQarg); ! 18735: } ! 18736: appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" ! 18737: " ORDER BY snum, rowid", 0); ! 18738: if( bDebug ){ ! 18739: utf8_printf(p->out, "SQL: %s;\n", sSelect.z); 1.2 misho 18740: }else{ 1.5 ! misho 18741: rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); 1.2 misho 18742: } 1.5 ! misho 18743: freeText(&sSelect); 1.2 misho 18744: } 18745: if( zErrMsg ){ 1.4 misho 18746: utf8_printf(stderr,"Error: %s\n", zErrMsg); 1.2 misho 18747: sqlite3_free(zErrMsg); 18748: rc = 1; 18749: }else if( rc != SQLITE_OK ){ 1.4 misho 18750: raw_printf(stderr,"Error: querying schema information\n"); 1.2 misho 18751: rc = 1; 18752: }else{ 18753: rc = 0; 18754: } 18755: }else 18756: 1.4 misho 18757: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) 18758: if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ 1.5 ! misho 18759: sqlite3_unsupported_selecttrace = nArg>=2 ? (int)integerValue(azArg[1]) : 0xffff; 1.4 misho 18760: }else 18761: #endif 18762: 18763: #if defined(SQLITE_ENABLE_SESSION) 18764: if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ 18765: OpenSession *pSession = &p->aSession[0]; 18766: char **azCmd = &azArg[1]; 18767: int iSes = 0; 18768: int nCmd = nArg - 1; 18769: int i; 18770: if( nArg<=1 ) goto session_syntax_error; 18771: open_db(p, 0); 18772: if( nArg>=3 ){ 18773: for(iSes=0; iSes<p->nSession; iSes++){ 18774: if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break; 18775: } 18776: if( iSes<p->nSession ){ 18777: pSession = &p->aSession[iSes]; 18778: azCmd++; 18779: nCmd--; 18780: }else{ 18781: pSession = &p->aSession[0]; 18782: iSes = 0; 18783: } 18784: } 18785: 18786: /* .session attach TABLE 18787: ** Invoke the sqlite3session_attach() interface to attach a particular 18788: ** table so that it is never filtered. 18789: */ 18790: if( strcmp(azCmd[0],"attach")==0 ){ 18791: if( nCmd!=2 ) goto session_syntax_error; 18792: if( pSession->p==0 ){ 18793: session_not_open: 18794: raw_printf(stderr, "ERROR: No sessions are open\n"); 18795: }else{ 18796: rc = sqlite3session_attach(pSession->p, azCmd[1]); 18797: if( rc ){ 18798: raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); 18799: rc = 0; 18800: } 18801: } 18802: }else 18803: 18804: /* .session changeset FILE 18805: ** .session patchset FILE 18806: ** Write a changeset or patchset into a file. The file is overwritten. 18807: */ 18808: if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){ 18809: FILE *out = 0; 18810: if( nCmd!=2 ) goto session_syntax_error; 18811: if( pSession->p==0 ) goto session_not_open; 18812: out = fopen(azCmd[1], "wb"); 18813: if( out==0 ){ 1.5 ! misho 18814: utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", ! 18815: azCmd[1]); 1.4 misho 18816: }else{ 18817: int szChng; 18818: void *pChng; 18819: if( azCmd[0][0]=='c' ){ 18820: rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); 18821: }else{ 18822: rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); 18823: } 18824: if( rc ){ 18825: printf("Error: error code %d\n", rc); 18826: rc = 0; 18827: } 18828: if( pChng 18829: && fwrite(pChng, szChng, 1, out)!=1 ){ 18830: raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", 18831: szChng); 18832: } 18833: sqlite3_free(pChng); 18834: fclose(out); 18835: } 18836: }else 18837: 18838: /* .session close 18839: ** Close the identified session 18840: */ 18841: if( strcmp(azCmd[0], "close")==0 ){ 18842: if( nCmd!=1 ) goto session_syntax_error; 18843: if( p->nSession ){ 18844: session_close(pSession); 18845: p->aSession[iSes] = p->aSession[--p->nSession]; 18846: } 18847: }else 18848: 18849: /* .session enable ?BOOLEAN? 18850: ** Query or set the enable flag 18851: */ 18852: if( strcmp(azCmd[0], "enable")==0 ){ 18853: int ii; 18854: if( nCmd>2 ) goto session_syntax_error; 18855: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); 18856: if( p->nSession ){ 18857: ii = sqlite3session_enable(pSession->p, ii); 18858: utf8_printf(p->out, "session %s enable flag = %d\n", 18859: pSession->zName, ii); 18860: } 18861: }else 18862: 18863: /* .session filter GLOB .... 18864: ** Set a list of GLOB patterns of table names to be excluded. 18865: */ 18866: if( strcmp(azCmd[0], "filter")==0 ){ 18867: int ii, nByte; 18868: if( nCmd<2 ) goto session_syntax_error; 18869: if( p->nSession ){ 18870: for(ii=0; ii<pSession->nFilter; ii++){ 18871: sqlite3_free(pSession->azFilter[ii]); 18872: } 18873: sqlite3_free(pSession->azFilter); 18874: nByte = sizeof(pSession->azFilter[0])*(nCmd-1); 18875: pSession->azFilter = sqlite3_malloc( nByte ); 18876: if( pSession->azFilter==0 ){ 18877: raw_printf(stderr, "Error: out or memory\n"); 18878: exit(1); 18879: } 18880: for(ii=1; ii<nCmd; ii++){ 18881: pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); 18882: } 18883: pSession->nFilter = ii-1; 18884: } 18885: }else 18886: 18887: /* .session indirect ?BOOLEAN? 18888: ** Query or set the indirect flag 18889: */ 18890: if( strcmp(azCmd[0], "indirect")==0 ){ 18891: int ii; 18892: if( nCmd>2 ) goto session_syntax_error; 18893: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); 18894: if( p->nSession ){ 18895: ii = sqlite3session_indirect(pSession->p, ii); 18896: utf8_printf(p->out, "session %s indirect flag = %d\n", 18897: pSession->zName, ii); 18898: } 18899: }else 18900: 18901: /* .session isempty 18902: ** Determine if the session is empty 18903: */ 18904: if( strcmp(azCmd[0], "isempty")==0 ){ 18905: int ii; 18906: if( nCmd!=1 ) goto session_syntax_error; 18907: if( p->nSession ){ 18908: ii = sqlite3session_isempty(pSession->p); 18909: utf8_printf(p->out, "session %s isempty flag = %d\n", 18910: pSession->zName, ii); 18911: } 18912: }else 18913: 18914: /* .session list 18915: ** List all currently open sessions 18916: */ 18917: if( strcmp(azCmd[0],"list")==0 ){ 18918: for(i=0; i<p->nSession; i++){ 18919: utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName); 18920: } 18921: }else 18922: 18923: /* .session open DB NAME 18924: ** Open a new session called NAME on the attached database DB. 18925: ** DB is normally "main". 18926: */ 18927: if( strcmp(azCmd[0],"open")==0 ){ 18928: char *zName; 18929: if( nCmd!=3 ) goto session_syntax_error; 18930: zName = azCmd[2]; 18931: if( zName[0]==0 ) goto session_syntax_error; 18932: for(i=0; i<p->nSession; i++){ 18933: if( strcmp(p->aSession[i].zName,zName)==0 ){ 18934: utf8_printf(stderr, "Session \"%s\" already exists\n", zName); 18935: goto meta_command_exit; 18936: } 18937: } 18938: if( p->nSession>=ArraySize(p->aSession) ){ 18939: raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession)); 18940: goto meta_command_exit; 18941: } 18942: pSession = &p->aSession[p->nSession]; 18943: rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); 18944: if( rc ){ 18945: raw_printf(stderr, "Cannot open session: error code=%d\n", rc); 18946: rc = 0; 18947: goto meta_command_exit; 18948: } 18949: pSession->nFilter = 0; 18950: sqlite3session_table_filter(pSession->p, session_filter, pSession); 18951: p->nSession++; 18952: pSession->zName = sqlite3_mprintf("%s", zName); 18953: }else 18954: /* If no command name matches, show a syntax error */ 18955: session_syntax_error: 1.5 ! misho 18956: showHelp(p->out, "session"); 1.4 misho 18957: }else 18958: #endif 18959: 18960: #ifdef SQLITE_DEBUG 18961: /* Undocumented commands for internal testing. Subject to change 18962: ** without notice. */ 18963: if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ 18964: if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ 18965: int i, v; 18966: for(i=1; i<nArg; i++){ 18967: v = booleanValue(azArg[i]); 18968: utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); 18969: } 18970: } 18971: if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ 18972: int i; sqlite3_int64 v; 18973: for(i=1; i<nArg; i++){ 18974: char zBuf[200]; 18975: v = integerValue(azArg[i]); 18976: sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v); 18977: utf8_printf(p->out, "%s", zBuf); 18978: } 18979: } 18980: }else 18981: #endif 18982: 1.5 ! misho 18983: if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ ! 18984: int bIsInit = 0; /* True to initialize the SELFTEST table */ ! 18985: int bVerbose = 0; /* Verbose output */ ! 18986: int bSelftestExists; /* True if SELFTEST already exists */ ! 18987: int i, k; /* Loop counters */ ! 18988: int nTest = 0; /* Number of tests runs */ ! 18989: int nErr = 0; /* Number of errors seen */ ! 18990: ShellText str; /* Answer for a query */ ! 18991: sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ ! 18992: ! 18993: open_db(p,0); ! 18994: for(i=1; i<nArg; i++){ ! 18995: const char *z = azArg[i]; ! 18996: if( z[0]=='-' && z[1]=='-' ) z++; ! 18997: if( strcmp(z,"-init")==0 ){ ! 18998: bIsInit = 1; ! 18999: }else ! 19000: if( strcmp(z,"-v")==0 ){ ! 19001: bVerbose++; ! 19002: }else ! 19003: { ! 19004: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", ! 19005: azArg[i], azArg[0]); ! 19006: raw_printf(stderr, "Should be one of: --init -v\n"); ! 19007: rc = 1; ! 19008: goto meta_command_exit; ! 19009: } ! 19010: } ! 19011: if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0) ! 19012: != SQLITE_OK ){ ! 19013: bSelftestExists = 0; ! 19014: }else{ ! 19015: bSelftestExists = 1; ! 19016: } ! 19017: if( bIsInit ){ ! 19018: createSelftestTable(p); ! 19019: bSelftestExists = 1; ! 19020: } ! 19021: initText(&str); ! 19022: appendText(&str, "x", 0); ! 19023: for(k=bSelftestExists; k>=0; k--){ ! 19024: if( k==1 ){ ! 19025: rc = sqlite3_prepare_v2(p->db, ! 19026: "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", ! 19027: -1, &pStmt, 0); ! 19028: }else{ ! 19029: rc = sqlite3_prepare_v2(p->db, ! 19030: "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," ! 19031: " (1,'run','PRAGMA integrity_check','ok')", ! 19032: -1, &pStmt, 0); ! 19033: } ! 19034: if( rc ){ ! 19035: raw_printf(stderr, "Error querying the selftest table\n"); ! 19036: rc = 1; ! 19037: sqlite3_finalize(pStmt); ! 19038: goto meta_command_exit; ! 19039: } ! 19040: for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ ! 19041: int tno = sqlite3_column_int(pStmt, 0); ! 19042: const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); ! 19043: const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); ! 19044: const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); ! 19045: ! 19046: k = 0; ! 19047: if( bVerbose>0 ){ ! 19048: char *zQuote = sqlite3_mprintf("%q", zSql); ! 19049: printf("%d: %s %s\n", tno, zOp, zSql); ! 19050: sqlite3_free(zQuote); ! 19051: } ! 19052: if( strcmp(zOp,"memo")==0 ){ ! 19053: utf8_printf(p->out, "%s\n", zSql); ! 19054: }else ! 19055: if( strcmp(zOp,"run")==0 ){ ! 19056: char *zErrMsg = 0; ! 19057: str.n = 0; ! 19058: str.z[0] = 0; ! 19059: rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); ! 19060: nTest++; ! 19061: if( bVerbose ){ ! 19062: utf8_printf(p->out, "Result: %s\n", str.z); ! 19063: } ! 19064: if( rc || zErrMsg ){ ! 19065: nErr++; ! 19066: rc = 1; ! 19067: utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); ! 19068: sqlite3_free(zErrMsg); ! 19069: }else if( strcmp(zAns,str.z)!=0 ){ ! 19070: nErr++; ! 19071: rc = 1; ! 19072: utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); ! 19073: utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); ! 19074: } ! 19075: }else ! 19076: { ! 19077: utf8_printf(stderr, ! 19078: "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); ! 19079: rc = 1; ! 19080: break; ! 19081: } ! 19082: } /* End loop over rows of content from SELFTEST */ ! 19083: sqlite3_finalize(pStmt); ! 19084: } /* End loop over k */ ! 19085: freeText(&str); ! 19086: utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); ! 19087: }else ! 19088: 1.4 misho 19089: if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ 19090: if( nArg<2 || nArg>3 ){ 19091: raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); 19092: rc = 1; 19093: } 19094: if( nArg>=2 ){ 19095: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, 19096: "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); 19097: } 19098: if( nArg>=3 ){ 19099: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, 19100: "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); 19101: } 19102: }else 19103: 1.5 ! misho 19104: if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){ ! 19105: const char *zLike = 0; /* Which table to checksum. 0 means everything */ ! 19106: int i; /* Loop counter */ ! 19107: int bSchema = 0; /* Also hash the schema */ ! 19108: int bSeparate = 0; /* Hash each table separately */ ! 19109: int iSize = 224; /* Hash algorithm to use */ ! 19110: int bDebug = 0; /* Only show the query that would have run */ ! 19111: sqlite3_stmt *pStmt; /* For querying tables names */ ! 19112: char *zSql; /* SQL to be run */ ! 19113: char *zSep; /* Separator */ ! 19114: ShellText sSql; /* Complete SQL for the query to run the hash */ ! 19115: ShellText sQuery; /* Set of queries used to read all content */ ! 19116: open_db(p, 0); ! 19117: for(i=1; i<nArg; i++){ ! 19118: const char *z = azArg[i]; ! 19119: if( z[0]=='-' ){ ! 19120: z++; ! 19121: if( z[0]=='-' ) z++; ! 19122: if( strcmp(z,"schema")==0 ){ ! 19123: bSchema = 1; ! 19124: }else ! 19125: if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0 ! 19126: || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0 ! 19127: ){ ! 19128: iSize = atoi(&z[5]); ! 19129: }else ! 19130: if( strcmp(z,"debug")==0 ){ ! 19131: bDebug = 1; ! 19132: }else ! 19133: { ! 19134: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", ! 19135: azArg[i], azArg[0]); ! 19136: showHelp(p->out, azArg[0]); ! 19137: rc = 1; ! 19138: goto meta_command_exit; ! 19139: } ! 19140: }else if( zLike ){ ! 19141: raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); ! 19142: rc = 1; ! 19143: goto meta_command_exit; ! 19144: }else{ ! 19145: zLike = z; ! 19146: bSeparate = 1; ! 19147: if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1; ! 19148: } ! 19149: } ! 19150: if( bSchema ){ ! 19151: zSql = "SELECT lower(name) FROM sqlite_schema" ! 19152: " WHERE type='table' AND coalesce(rootpage,0)>1" ! 19153: " UNION ALL SELECT 'sqlite_schema'" ! 19154: " ORDER BY 1 collate nocase"; ! 19155: }else{ ! 19156: zSql = "SELECT lower(name) FROM sqlite_schema" ! 19157: " WHERE type='table' AND coalesce(rootpage,0)>1" ! 19158: " AND name NOT LIKE 'sqlite_%'" ! 19159: " ORDER BY 1 collate nocase"; ! 19160: } ! 19161: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); ! 19162: initText(&sQuery); ! 19163: initText(&sSql); ! 19164: appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); ! 19165: zSep = "VALUES("; ! 19166: while( SQLITE_ROW==sqlite3_step(pStmt) ){ ! 19167: const char *zTab = (const char*)sqlite3_column_text(pStmt,0); ! 19168: if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; ! 19169: if( strncmp(zTab, "sqlite_",7)!=0 ){ ! 19170: appendText(&sQuery,"SELECT * FROM ", 0); ! 19171: appendText(&sQuery,zTab,'"'); ! 19172: appendText(&sQuery," NOT INDEXED;", 0); ! 19173: }else if( strcmp(zTab, "sqlite_schema")==0 ){ ! 19174: appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema" ! 19175: " ORDER BY name;", 0); ! 19176: }else if( strcmp(zTab, "sqlite_sequence")==0 ){ ! 19177: appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence" ! 19178: " ORDER BY name;", 0); ! 19179: }else if( strcmp(zTab, "sqlite_stat1")==0 ){ ! 19180: appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" ! 19181: " ORDER BY tbl,idx;", 0); ! 19182: }else if( strcmp(zTab, "sqlite_stat4")==0 ){ ! 19183: appendText(&sQuery, "SELECT * FROM ", 0); ! 19184: appendText(&sQuery, zTab, 0); ! 19185: appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); ! 19186: } ! 19187: appendText(&sSql, zSep, 0); ! 19188: appendText(&sSql, sQuery.z, '\''); ! 19189: sQuery.n = 0; ! 19190: appendText(&sSql, ",", 0); ! 19191: appendText(&sSql, zTab, '\''); ! 19192: zSep = "),("; ! 19193: } ! 19194: sqlite3_finalize(pStmt); ! 19195: if( bSeparate ){ ! 19196: zSql = sqlite3_mprintf( ! 19197: "%s))" ! 19198: " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label" ! 19199: " FROM [sha3sum$query]", ! 19200: sSql.z, iSize); ! 19201: }else{ ! 19202: zSql = sqlite3_mprintf( ! 19203: "%s))" ! 19204: " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash" ! 19205: " FROM [sha3sum$query]", ! 19206: sSql.z, iSize); ! 19207: } ! 19208: freeText(&sQuery); ! 19209: freeText(&sSql); ! 19210: if( bDebug ){ ! 19211: utf8_printf(p->out, "%s\n", zSql); ! 19212: }else{ ! 19213: shell_exec(p, zSql, 0); ! 19214: } ! 19215: sqlite3_free(zSql); ! 19216: }else ! 19217: ! 19218: #ifndef SQLITE_NOHAVE_SYSTEM 1.4 misho 19219: if( c=='s' 19220: && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) 19221: ){ 19222: char *zCmd; 19223: int i, x; 19224: if( nArg<2 ){ 19225: raw_printf(stderr, "Usage: .system COMMAND\n"); 19226: rc = 1; 19227: goto meta_command_exit; 19228: } 19229: zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); 19230: for(i=2; i<nArg; i++){ 19231: zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"", 19232: zCmd, azArg[i]); 19233: } 19234: x = system(zCmd); 19235: sqlite3_free(zCmd); 19236: if( x ) raw_printf(stderr, "System command returns %d\n", x); 1.2 misho 19237: }else 1.5 ! misho 19238: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ 1.2 misho 19239: 1.4 misho 19240: if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ 1.5 ! misho 19241: static const char *azBool[] = { "off", "on", "trigger", "full"}; 1.2 misho 19242: int i; 1.4 misho 19243: if( nArg!=1 ){ 19244: raw_printf(stderr, "Usage: .show\n"); 19245: rc = 1; 19246: goto meta_command_exit; 19247: } 1.5 ! misho 19248: utf8_printf(p->out, "%12.12s: %s\n","echo", ! 19249: azBool[ShellHasFlag(p, SHFLG_Echo)]); 1.4 misho 19250: utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); 19251: utf8_printf(p->out, "%12.12s: %s\n","explain", 19252: p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); 19253: utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); 19254: utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); 19255: utf8_printf(p->out, "%12.12s: ", "nullvalue"); 19256: output_c_string(p->out, p->nullValue); 19257: raw_printf(p->out, "\n"); 19258: utf8_printf(p->out,"%12.12s: %s\n","output", 1.2 misho 19259: strlen30(p->outfile) ? p->outfile : "stdout"); 1.4 misho 19260: utf8_printf(p->out,"%12.12s: ", "colseparator"); 19261: output_c_string(p->out, p->colSeparator); 19262: raw_printf(p->out, "\n"); 19263: utf8_printf(p->out,"%12.12s: ", "rowseparator"); 19264: output_c_string(p->out, p->rowSeparator); 19265: raw_printf(p->out, "\n"); 19266: utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]); 19267: utf8_printf(p->out, "%12.12s: ", "width"); 1.5 ! misho 19268: for (i=0;i<p->nWidth;i++) { 1.4 misho 19269: raw_printf(p->out, "%d ", p->colWidth[i]); 1.2 misho 19270: } 1.4 misho 19271: raw_printf(p->out, "\n"); 1.5 ! misho 19272: utf8_printf(p->out, "%12.12s: %s\n", "filename", ! 19273: p->zDbFilename ? p->zDbFilename : ""); 1.2 misho 19274: }else 19275: 1.4 misho 19276: if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ 19277: if( nArg==2 ){ 1.5 ! misho 19278: p->statsOn = (u8)booleanValue(azArg[1]); 1.4 misho 19279: }else if( nArg==1 ){ 19280: display_stats(p->db, p, 0); 19281: }else{ 19282: raw_printf(stderr, "Usage: .stats ?on|off?\n"); 19283: rc = 1; 19284: } 1.2 misho 19285: }else 19286: 1.5 ! misho 19287: if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0) ! 19288: || (c=='i' && (strncmp(azArg[0], "indices", n)==0 ! 19289: || strncmp(azArg[0], "indexes", n)==0) ) ! 19290: ){ 1.3 misho 19291: sqlite3_stmt *pStmt; 1.2 misho 19292: char **azResult; 1.3 misho 19293: int nRow, nAlloc; 19294: int ii; 1.5 ! misho 19295: ShellText s; ! 19296: initText(&s); 1.4 misho 19297: open_db(p, 0); 1.3 misho 19298: rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); 1.5 ! misho 19299: if( rc ){ ! 19300: sqlite3_finalize(pStmt); ! 19301: return shellDatabaseError(p->db); ! 19302: } 1.4 misho 19303: 1.5 ! misho 19304: if( nArg>2 && c=='i' ){ ! 19305: /* It is an historical accident that the .indexes command shows an error ! 19306: ** when called with the wrong number of arguments whereas the .tables ! 19307: ** command does not. */ ! 19308: raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); ! 19309: rc = 1; ! 19310: sqlite3_finalize(pStmt); ! 19311: goto meta_command_exit; ! 19312: } ! 19313: for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ 1.3 misho 19314: const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); 1.5 ! misho 19315: if( zDbName==0 ) continue; ! 19316: if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); ! 19317: if( sqlite3_stricmp(zDbName, "main")==0 ){ ! 19318: appendText(&s, "SELECT name FROM ", 0); ! 19319: }else{ ! 19320: appendText(&s, "SELECT ", 0); ! 19321: appendText(&s, zDbName, '\''); ! 19322: appendText(&s, "||'.'||name FROM ", 0); ! 19323: } ! 19324: appendText(&s, zDbName, '"'); ! 19325: appendText(&s, ".sqlite_schema ", 0); ! 19326: if( c=='t' ){ ! 19327: appendText(&s," WHERE type IN ('table','view')" ! 19328: " AND name NOT LIKE 'sqlite_%'" ! 19329: " AND name LIKE ?1", 0); 1.3 misho 19330: }else{ 1.5 ! misho 19331: appendText(&s," WHERE type='index'" ! 19332: " AND tbl_name LIKE ?1", 0); 1.3 misho 19333: } 19334: } 1.4 misho 19335: rc = sqlite3_finalize(pStmt); 1.5 ! misho 19336: appendText(&s, " ORDER BY 1", 0); ! 19337: rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); ! 19338: freeText(&s); 1.4 misho 19339: if( rc ) return shellDatabaseError(p->db); 19340: 19341: /* Run the SQL statement prepared by the above block. Store the results 19342: ** as an array of nul-terminated strings in azResult[]. */ 1.3 misho 19343: nRow = nAlloc = 0; 19344: azResult = 0; 19345: if( nArg>1 ){ 19346: sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); 1.2 misho 19347: }else{ 1.3 misho 19348: sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); 19349: } 19350: while( sqlite3_step(pStmt)==SQLITE_ROW ){ 19351: if( nRow>=nAlloc ){ 19352: char **azNew; 1.4 misho 19353: int n2 = nAlloc*2 + 10; 19354: azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); 1.5 ! misho 19355: if( azNew==0 ) shell_out_of_memory(); 1.4 misho 19356: nAlloc = n2; 1.3 misho 19357: azResult = azNew; 19358: } 19359: azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); 1.5 ! misho 19360: if( 0==azResult[nRow] ) shell_out_of_memory(); 1.4 misho 19361: nRow++; 1.2 misho 19362: } 1.4 misho 19363: if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ 19364: rc = shellDatabaseError(p->db); 19365: } 19366: 19367: /* Pretty-print the contents of array azResult[] to the output */ 19368: if( rc==0 && nRow>0 ){ 1.2 misho 19369: int len, maxlen = 0; 19370: int i, j; 19371: int nPrintCol, nPrintRow; 1.3 misho 19372: for(i=0; i<nRow; i++){ 1.2 misho 19373: len = strlen30(azResult[i]); 19374: if( len>maxlen ) maxlen = len; 19375: } 19376: nPrintCol = 80/(maxlen+2); 19377: if( nPrintCol<1 ) nPrintCol = 1; 19378: nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; 19379: for(i=0; i<nPrintRow; i++){ 1.3 misho 19380: for(j=i; j<nRow; j+=nPrintRow){ 19381: char *zSp = j<nPrintRow ? "" : " "; 1.4 misho 19382: utf8_printf(p->out, "%s%-*s", zSp, maxlen, 19383: azResult[j] ? azResult[j]:""); 1.2 misho 19384: } 1.4 misho 19385: raw_printf(p->out, "\n"); 1.2 misho 19386: } 19387: } 1.4 misho 19388: 1.3 misho 19389: for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); 19390: sqlite3_free(azResult); 1.2 misho 19391: }else 19392: 1.5 ! misho 19393: /* Begin redirecting output to the file "testcase-out.txt" */ ! 19394: if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ ! 19395: output_reset(p); ! 19396: p->out = output_file_open("testcase-out.txt", 0); ! 19397: if( p->out==0 ){ ! 19398: raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); ! 19399: } ! 19400: if( nArg>=2 ){ ! 19401: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); ! 19402: }else{ ! 19403: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); ! 19404: } ! 19405: }else ! 19406: ! 19407: #ifndef SQLITE_UNTESTABLE ! 19408: if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){ 1.2 misho 19409: static const struct { 19410: const char *zCtrlName; /* Name of a test-control option */ 19411: int ctrlCode; /* Integer code for that option */ 1.5 ! misho 19412: const char *zUsage; /* Usage notes */ 1.2 misho 19413: } aCtrl[] = { 1.5 ! misho 19414: { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, ! 19415: { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, ! 19416: /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ ! 19417: /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ ! 19418: { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, ! 19419: { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, ! 19420: /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/ ! 19421: { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, ! 19422: { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" }, ! 19423: { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, ! 19424: { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, ! 19425: { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, ! 19426: #ifdef YYCOVERAGE ! 19427: { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, ! 19428: #endif ! 19429: { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, ! 19430: { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, ! 19431: { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, ! 19432: { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, 1.2 misho 19433: }; 19434: int testctrl = -1; 1.5 ! misho 19435: int iCtrl = -1; ! 19436: int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ ! 19437: int isOk = 0; 1.4 misho 19438: int i, n2; 1.5 ! misho 19439: const char *zCmd = 0; ! 19440: 1.4 misho 19441: open_db(p, 0); 1.5 ! misho 19442: zCmd = nArg>=2 ? azArg[1] : "help"; ! 19443: ! 19444: /* The argument can optionally begin with "-" or "--" */ ! 19445: if( zCmd[0]=='-' && zCmd[1] ){ ! 19446: zCmd++; ! 19447: if( zCmd[0]=='-' && zCmd[1] ) zCmd++; ! 19448: } ! 19449: ! 19450: /* --help lists all test-controls */ ! 19451: if( strcmp(zCmd,"help")==0 ){ ! 19452: utf8_printf(p->out, "Available test-controls:\n"); ! 19453: for(i=0; i<ArraySize(aCtrl); i++){ ! 19454: utf8_printf(p->out, " .testctrl %s %s\n", ! 19455: aCtrl[i].zCtrlName, aCtrl[i].zUsage); ! 19456: } ! 19457: rc = 1; ! 19458: goto meta_command_exit; ! 19459: } 1.2 misho 19460: 19461: /* convert testctrl text option to value. allow any unique prefix 19462: ** of the option name, or a numerical value. */ 1.5 ! misho 19463: n2 = strlen30(zCmd); 1.4 misho 19464: for(i=0; i<ArraySize(aCtrl); i++){ 1.5 ! misho 19465: if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){ 1.2 misho 19466: if( testctrl<0 ){ 19467: testctrl = aCtrl[i].ctrlCode; 1.5 ! misho 19468: iCtrl = i; 1.2 misho 19469: }else{ 1.5 ! misho 19470: utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n" ! 19471: "Use \".testctrl --help\" for help\n", zCmd); ! 19472: rc = 1; ! 19473: goto meta_command_exit; 1.2 misho 19474: } 19475: } 19476: } 1.5 ! misho 19477: if( testctrl<0 ){ ! 19478: utf8_printf(stderr,"Error: unknown test-control: %s\n" ! 19479: "Use \".testctrl --help\" for help\n", zCmd); 1.2 misho 19480: }else{ 19481: switch(testctrl){ 19482: 19483: /* sqlite3_test_control(int, db, int) */ 19484: case SQLITE_TESTCTRL_OPTIMIZATIONS: 19485: if( nArg==3 ){ 1.4 misho 19486: int opt = (int)strtol(azArg[2], 0, 0); 19487: rc2 = sqlite3_test_control(testctrl, p->db, opt); 1.5 ! misho 19488: isOk = 3; 1.2 misho 19489: } 19490: break; 19491: 19492: /* sqlite3_test_control(int) */ 1.4 misho 19493: case SQLITE_TESTCTRL_PRNG_SAVE: 19494: case SQLITE_TESTCTRL_PRNG_RESTORE: 1.2 misho 19495: case SQLITE_TESTCTRL_PRNG_RESET: 1.4 misho 19496: case SQLITE_TESTCTRL_BYTEORDER: 1.2 misho 19497: if( nArg==2 ){ 1.4 misho 19498: rc2 = sqlite3_test_control(testctrl); 1.5 ! misho 19499: isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3; 1.2 misho 19500: } 19501: break; 19502: 19503: /* sqlite3_test_control(int, uint) */ 1.4 misho 19504: case SQLITE_TESTCTRL_PENDING_BYTE: 1.2 misho 19505: if( nArg==3 ){ 1.4 misho 19506: unsigned int opt = (unsigned int)integerValue(azArg[2]); 19507: rc2 = sqlite3_test_control(testctrl, opt); 1.5 ! misho 19508: isOk = 3; ! 19509: } ! 19510: break; ! 19511: ! 19512: /* sqlite3_test_control(int, int, sqlite3*) */ ! 19513: case SQLITE_TESTCTRL_PRNG_SEED: ! 19514: if( nArg==3 || nArg==4 ){ ! 19515: int ii = (int)integerValue(azArg[2]); ! 19516: sqlite3 *db; ! 19517: if( ii==0 && strcmp(azArg[2],"random")==0 ){ ! 19518: sqlite3_randomness(sizeof(ii),&ii); ! 19519: printf("-- random seed: %d\n", ii); ! 19520: } ! 19521: if( nArg==3 ){ ! 19522: db = 0; ! 19523: }else{ ! 19524: db = p->db; ! 19525: /* Make sure the schema has been loaded */ ! 19526: sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0); ! 19527: } ! 19528: rc2 = sqlite3_test_control(testctrl, ii, db); ! 19529: isOk = 3; 1.2 misho 19530: } 19531: break; 1.4 misho 19532: 1.2 misho 19533: /* sqlite3_test_control(int, int) */ 1.4 misho 19534: case SQLITE_TESTCTRL_ASSERT: 19535: case SQLITE_TESTCTRL_ALWAYS: 1.2 misho 19536: if( nArg==3 ){ 1.4 misho 19537: int opt = booleanValue(azArg[2]); 19538: rc2 = sqlite3_test_control(testctrl, opt); 1.5 ! misho 19539: isOk = 1; 1.2 misho 19540: } 19541: break; 19542: 1.5 ! misho 19543: /* sqlite3_test_control(int, int) */ ! 19544: case SQLITE_TESTCTRL_LOCALTIME_FAULT: ! 19545: case SQLITE_TESTCTRL_NEVER_CORRUPT: 1.2 misho 19546: if( nArg==3 ){ 1.5 ! misho 19547: int opt = booleanValue(azArg[2]); 1.4 misho 19548: rc2 = sqlite3_test_control(testctrl, opt); 1.5 ! misho 19549: isOk = 3; 1.2 misho 19550: } 19551: break; 1.5 ! misho 19552: ! 19553: /* sqlite3_test_control(sqlite3*) */ ! 19554: case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: ! 19555: rc2 = sqlite3_test_control(testctrl, p->db); ! 19556: isOk = 3; ! 19557: break; 1.2 misho 19558: 1.4 misho 19559: case SQLITE_TESTCTRL_IMPOSTER: 19560: if( nArg==5 ){ 19561: rc2 = sqlite3_test_control(testctrl, p->db, 19562: azArg[2], 19563: integerValue(azArg[3]), 19564: integerValue(azArg[4])); 1.5 ! misho 19565: isOk = 3; 1.4 misho 19566: } 19567: break; 19568: 1.5 ! misho 19569: #ifdef YYCOVERAGE ! 19570: case SQLITE_TESTCTRL_PARSER_COVERAGE: ! 19571: if( nArg==2 ){ ! 19572: sqlite3_test_control(testctrl, p->out); ! 19573: isOk = 3; ! 19574: } ! 19575: #endif 1.2 misho 19576: } 19577: } 1.5 ! misho 19578: if( isOk==0 && iCtrl>=0 ){ ! 19579: utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); ! 19580: rc = 1; ! 19581: }else if( isOk==1 ){ ! 19582: raw_printf(p->out, "%d\n", rc2); ! 19583: }else if( isOk==2 ){ ! 19584: raw_printf(p->out, "0x%08x\n", rc2); ! 19585: } 1.2 misho 19586: }else 1.5 ! misho 19587: #endif /* !defined(SQLITE_UNTESTABLE) */ 1.2 misho 19588: 1.4 misho 19589: if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ 19590: open_db(p, 0); 19591: sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); 19592: }else 19593: 19594: if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ 19595: if( nArg==2 ){ 19596: enableTimer = booleanValue(azArg[1]); 19597: if( enableTimer && !HAS_TIMER ){ 19598: raw_printf(stderr, "Error: timer not available on this system.\n"); 19599: enableTimer = 0; 19600: } 19601: }else{ 19602: raw_printf(stderr, "Usage: .timer on|off\n"); 19603: rc = 1; 19604: } 1.2 misho 19605: }else 1.4 misho 19606: 1.5 ! misho 19607: #ifndef SQLITE_OMIT_TRACE 1.4 misho 19608: if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ 1.5 ! misho 19609: int mType = 0; ! 19610: int jj; 1.4 misho 19611: open_db(p, 0); 1.5 ! misho 19612: for(jj=1; jj<nArg; jj++){ ! 19613: const char *z = azArg[jj]; ! 19614: if( z[0]=='-' ){ ! 19615: if( optionMatch(z, "expanded") ){ ! 19616: p->eTraceType = SHELL_TRACE_EXPANDED; ! 19617: } ! 19618: #ifdef SQLITE_ENABLE_NORMALIZE ! 19619: else if( optionMatch(z, "normalized") ){ ! 19620: p->eTraceType = SHELL_TRACE_NORMALIZED; ! 19621: } ! 19622: #endif ! 19623: else if( optionMatch(z, "plain") ){ ! 19624: p->eTraceType = SHELL_TRACE_PLAIN; ! 19625: } ! 19626: else if( optionMatch(z, "profile") ){ ! 19627: mType |= SQLITE_TRACE_PROFILE; ! 19628: } ! 19629: else if( optionMatch(z, "row") ){ ! 19630: mType |= SQLITE_TRACE_ROW; ! 19631: } ! 19632: else if( optionMatch(z, "stmt") ){ ! 19633: mType |= SQLITE_TRACE_STMT; ! 19634: } ! 19635: else if( optionMatch(z, "close") ){ ! 19636: mType |= SQLITE_TRACE_CLOSE; ! 19637: } ! 19638: else { ! 19639: raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z); ! 19640: rc = 1; ! 19641: goto meta_command_exit; ! 19642: } ! 19643: }else{ ! 19644: output_file_close(p->traceOut); ! 19645: p->traceOut = output_file_open(azArg[1], 0); ! 19646: } ! 19647: } ! 19648: if( p->traceOut==0 ){ ! 19649: sqlite3_trace_v2(p->db, 0, 0, 0); ! 19650: }else{ ! 19651: if( mType==0 ) mType = SQLITE_TRACE_STMT; ! 19652: sqlite3_trace_v2(p->db, mType, sql_trace_callback, p); ! 19653: } ! 19654: }else ! 19655: #endif /* !defined(SQLITE_OMIT_TRACE) */ ! 19656: ! 19657: #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE) ! 19658: if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ ! 19659: int ii; ! 19660: int lenOpt; ! 19661: char *zOpt; ! 19662: if( nArg<2 ){ ! 19663: raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); 1.4 misho 19664: rc = 1; 19665: goto meta_command_exit; 19666: } 1.5 ! misho 19667: open_db(p, 0); ! 19668: zOpt = azArg[1]; ! 19669: if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; ! 19670: lenOpt = (int)strlen(zOpt); ! 19671: if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ ! 19672: assert( azArg[nArg]==0 ); ! 19673: sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); 1.3 misho 19674: }else{ 1.5 ! misho 19675: for(ii=1; ii<nArg; ii++){ ! 19676: sqlite3_create_module(p->db, azArg[ii], 0, 0); ! 19677: } 1.3 misho 19678: } 1.5 ! misho 19679: }else 1.3 misho 19680: #endif 19681: 1.4 misho 19682: #if SQLITE_USER_AUTHENTICATION 19683: if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ 19684: if( nArg<2 ){ 19685: raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); 19686: rc = 1; 19687: goto meta_command_exit; 19688: } 19689: open_db(p, 0); 19690: if( strcmp(azArg[1],"login")==0 ){ 19691: if( nArg!=4 ){ 19692: raw_printf(stderr, "Usage: .user login USER PASSWORD\n"); 19693: rc = 1; 19694: goto meta_command_exit; 19695: } 19696: rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], 1.5 ! misho 19697: strlen30(azArg[3])); 1.4 misho 19698: if( rc ){ 19699: utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); 19700: rc = 1; 19701: } 19702: }else if( strcmp(azArg[1],"add")==0 ){ 19703: if( nArg!=5 ){ 19704: raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); 19705: rc = 1; 19706: goto meta_command_exit; 19707: } 1.5 ! misho 19708: rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]), 1.4 misho 19709: booleanValue(azArg[4])); 19710: if( rc ){ 19711: raw_printf(stderr, "User-Add failed: %d\n", rc); 19712: rc = 1; 19713: } 19714: }else if( strcmp(azArg[1],"edit")==0 ){ 19715: if( nArg!=5 ){ 19716: raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); 19717: rc = 1; 19718: goto meta_command_exit; 19719: } 1.5 ! misho 19720: rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]), 1.4 misho 19721: booleanValue(azArg[4])); 19722: if( rc ){ 19723: raw_printf(stderr, "User-Edit failed: %d\n", rc); 19724: rc = 1; 19725: } 19726: }else if( strcmp(azArg[1],"delete")==0 ){ 19727: if( nArg!=3 ){ 19728: raw_printf(stderr, "Usage: .user delete USER\n"); 19729: rc = 1; 19730: goto meta_command_exit; 19731: } 19732: rc = sqlite3_user_delete(p->db, azArg[2]); 19733: if( rc ){ 19734: raw_printf(stderr, "User-Delete failed: %d\n", rc); 19735: rc = 1; 19736: } 19737: }else{ 19738: raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); 19739: rc = 1; 19740: goto meta_command_exit; 19741: } 19742: }else 19743: #endif /* SQLITE_USER_AUTHENTICATION */ 19744: 1.2 misho 19745: if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ 1.4 misho 19746: utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, 1.2 misho 19747: sqlite3_libversion(), sqlite3_sourceid()); 1.5 ! misho 19748: #if SQLITE_HAVE_ZLIB ! 19749: utf8_printf(p->out, "zlib version %s\n", zlibVersion()); ! 19750: #endif ! 19751: #define CTIMEOPT_VAL_(opt) #opt ! 19752: #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) ! 19753: #if defined(__clang__) && defined(__clang_major__) ! 19754: utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "." ! 19755: CTIMEOPT_VAL(__clang_minor__) "." ! 19756: CTIMEOPT_VAL(__clang_patchlevel__) "\n"); ! 19757: #elif defined(_MSC_VER) ! 19758: utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n"); ! 19759: #elif defined(__GNUC__) && defined(__VERSION__) ! 19760: utf8_printf(p->out, "gcc-" __VERSION__ "\n"); ! 19761: #endif 1.2 misho 19762: }else 19763: 1.4 misho 19764: if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ 19765: const char *zDbName = nArg==2 ? azArg[1] : "main"; 1.5 ! misho 19766: sqlite3_vfs *pVfs = 0; 1.4 misho 19767: if( p->db ){ 19768: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); 19769: if( pVfs ){ 19770: utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); 19771: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); 19772: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); 19773: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); 19774: } 19775: } 19776: }else 19777: 19778: if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){ 19779: sqlite3_vfs *pVfs; 19780: sqlite3_vfs *pCurrent = 0; 19781: if( p->db ){ 19782: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent); 19783: } 19784: for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ 19785: utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, 19786: pVfs==pCurrent ? " <--- CURRENT" : ""); 19787: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); 19788: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); 19789: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); 19790: if( pVfs->pNext ){ 19791: raw_printf(p->out, "-----------------------------------\n"); 19792: } 19793: } 19794: }else 19795: 1.2 misho 19796: if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ 19797: const char *zDbName = nArg==2 ? azArg[1] : "main"; 19798: char *zVfsName = 0; 19799: if( p->db ){ 19800: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); 19801: if( zVfsName ){ 1.4 misho 19802: utf8_printf(p->out, "%s\n", zVfsName); 1.2 misho 19803: sqlite3_free(zVfsName); 19804: } 19805: } 19806: }else 19807: 1.3 misho 19808: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) 19809: if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ 1.4 misho 19810: sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; 1.3 misho 19811: }else 19812: #endif 19813: 1.4 misho 19814: if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ 1.2 misho 19815: int j; 19816: assert( nArg<=ArraySize(azArg) ); 1.5 ! misho 19817: p->nWidth = nArg-1; ! 19818: p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2); ! 19819: if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory(); ! 19820: if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth]; ! 19821: for(j=1; j<nArg; j++){ 1.4 misho 19822: p->colWidth[j-1] = (int)integerValue(azArg[j]); 1.2 misho 19823: } 19824: }else 19825: 19826: { 1.4 misho 19827: utf8_printf(stderr, "Error: unknown command or invalid arguments: " 1.2 misho 19828: " \"%s\". Enter \".help\" for help\n", azArg[0]); 19829: rc = 1; 19830: } 19831: 1.4 misho 19832: meta_command_exit: 19833: if( p->outCount ){ 19834: p->outCount--; 19835: if( p->outCount==0 ) output_reset(p); 19836: } 1.2 misho 19837: return rc; 19838: } 19839: 19840: /* 19841: ** Return TRUE if a semicolon occurs anywhere in the first N characters 19842: ** of string z[]. 19843: */ 1.4 misho 19844: static int line_contains_semicolon(const char *z, int N){ 1.2 misho 19845: int i; 19846: for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } 19847: return 0; 19848: } 19849: 19850: /* 19851: ** Test to see if a line consists entirely of whitespace. 19852: */ 19853: static int _all_whitespace(const char *z){ 19854: for(; *z; z++){ 19855: if( IsSpace(z[0]) ) continue; 19856: if( *z=='/' && z[1]=='*' ){ 19857: z += 2; 19858: while( *z && (*z!='*' || z[1]!='/') ){ z++; } 19859: if( *z==0 ) return 0; 19860: z++; 19861: continue; 19862: } 19863: if( *z=='-' && z[1]=='-' ){ 19864: z += 2; 19865: while( *z && *z!='\n' ){ z++; } 19866: if( *z==0 ) return 1; 19867: continue; 19868: } 19869: return 0; 19870: } 19871: return 1; 19872: } 19873: 19874: /* 19875: ** Return TRUE if the line typed in is an SQL command terminator other 19876: ** than a semi-colon. The SQL Server style "go" command is understood 19877: ** as is the Oracle "/". 19878: */ 1.4 misho 19879: static int line_is_command_terminator(const char *zLine){ 1.2 misho 19880: while( IsSpace(zLine[0]) ){ zLine++; }; 19881: if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){ 19882: return 1; /* Oracle */ 19883: } 19884: if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' 19885: && _all_whitespace(&zLine[2]) ){ 19886: return 1; /* SQL Server */ 19887: } 19888: return 0; 19889: } 19890: 19891: /* 1.5 ! misho 19892: ** We need a default sqlite3_complete() implementation to use in case ! 19893: ** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes ! 19894: ** any arbitrary text is a complete SQL statement. This is not very ! 19895: ** user-friendly, but it does seem to work. ! 19896: */ ! 19897: #ifdef SQLITE_OMIT_COMPLETE ! 19898: #define sqlite3_complete(x) 1 ! 19899: #endif ! 19900: ! 19901: /* 1.2 misho 19902: ** Return true if zSql is a complete SQL statement. Return false if it 19903: ** ends in the middle of a string literal or C-style comment. 19904: */ 1.4 misho 19905: static int line_is_complete(char *zSql, int nSql){ 1.2 misho 19906: int rc; 19907: if( zSql==0 ) return 1; 19908: zSql[nSql] = ';'; 19909: zSql[nSql+1] = 0; 19910: rc = sqlite3_complete(zSql); 19911: zSql[nSql] = 0; 19912: return rc; 19913: } 19914: 19915: /* 1.5 ! misho 19916: ** Run a single line of SQL. Return the number of errors. ! 19917: */ ! 19918: static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ ! 19919: int rc; ! 19920: char *zErrMsg = 0; ! 19921: ! 19922: open_db(p, 0); ! 19923: if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); ! 19924: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; ! 19925: BEGIN_TIMER; ! 19926: rc = shell_exec(p, zSql, &zErrMsg); ! 19927: END_TIMER; ! 19928: if( rc || zErrMsg ){ ! 19929: char zPrefix[100]; ! 19930: if( in!=0 || !stdin_is_interactive ){ ! 19931: sqlite3_snprintf(sizeof(zPrefix), zPrefix, ! 19932: "Error: near line %d:", startline); ! 19933: }else{ ! 19934: sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); ! 19935: } ! 19936: if( zErrMsg!=0 ){ ! 19937: utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); ! 19938: sqlite3_free(zErrMsg); ! 19939: zErrMsg = 0; ! 19940: }else{ ! 19941: utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); ! 19942: } ! 19943: return 1; ! 19944: }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ ! 19945: raw_printf(p->out, "changes: %3d total_changes: %d\n", ! 19946: sqlite3_changes(p->db), sqlite3_total_changes(p->db)); ! 19947: } ! 19948: return 0; ! 19949: } ! 19950: ! 19951: ! 19952: /* 1.2 misho 19953: ** Read input from *in and process it. If *in==0 then input 19954: ** is interactive - the user is typing it it. Otherwise, input 19955: ** is coming from a file or device. A prompt is issued and history 19956: ** is saved only if input is interactive. An interrupt signal will 19957: ** cause this routine to exit immediately, unless input is interactive. 19958: ** 19959: ** Return the number of errors. 19960: */ 1.5 ! misho 19961: static int process_input(ShellState *p){ 1.4 misho 19962: char *zLine = 0; /* A single input line */ 19963: char *zSql = 0; /* Accumulated SQL text */ 19964: int nLine; /* Length of current line */ 19965: int nSql = 0; /* Bytes of zSql[] used */ 19966: int nAlloc = 0; /* Allocated zSql[] space */ 19967: int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ 19968: int rc; /* Error code */ 19969: int errCnt = 0; /* Number of errors seen */ 19970: int startline = 0; /* Line number for start of current input */ 1.2 misho 19971: 1.5 ! misho 19972: p->lineno = 0; ! 19973: while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ 1.2 misho 19974: fflush(p->out); 1.5 ! misho 19975: zLine = one_input_line(p->in, zLine, nSql>0); 1.2 misho 19976: if( zLine==0 ){ 1.3 misho 19977: /* End of input */ 1.5 ! misho 19978: if( p->in==0 && stdin_is_interactive ) printf("\n"); 1.3 misho 19979: break; 1.2 misho 19980: } 19981: if( seenInterrupt ){ 1.5 ! misho 19982: if( p->in!=0 ) break; 1.2 misho 19983: seenInterrupt = 0; 19984: } 1.5 ! misho 19985: p->lineno++; 1.4 misho 19986: if( nSql==0 && _all_whitespace(zLine) ){ 1.5 ! misho 19987: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); 1.4 misho 19988: continue; 19989: } 1.5 ! misho 19990: if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ ! 19991: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); ! 19992: if( zLine[0]=='.' ){ ! 19993: rc = do_meta_command(zLine, p); ! 19994: if( rc==2 ){ /* exit requested */ ! 19995: break; ! 19996: }else if( rc ){ ! 19997: errCnt++; ! 19998: } 1.2 misho 19999: } 20000: continue; 20001: } 1.4 misho 20002: if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ 1.2 misho 20003: memcpy(zLine,";",2); 20004: } 1.4 misho 20005: nLine = strlen30(zLine); 20006: if( nSql+nLine+2>=nAlloc ){ 20007: nAlloc = nSql+nLine+100; 20008: zSql = realloc(zSql, nAlloc); 1.5 ! misho 20009: if( zSql==0 ) shell_out_of_memory(); 1.4 misho 20010: } 1.2 misho 20011: nSqlPrior = nSql; 1.4 misho 20012: if( nSql==0 ){ 1.2 misho 20013: int i; 20014: for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} 1.4 misho 20015: assert( nAlloc>0 && zSql!=0 ); 20016: memcpy(zSql, zLine+i, nLine+1-i); 1.5 ! misho 20017: startline = p->lineno; 1.4 misho 20018: nSql = nLine-i; 1.2 misho 20019: }else{ 20020: zSql[nSql++] = '\n'; 1.4 misho 20021: memcpy(zSql+nSql, zLine, nLine+1); 20022: nSql += nLine; 1.2 misho 20023: } 1.4 misho 20024: if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) 1.2 misho 20025: && sqlite3_complete(zSql) ){ 1.5 ! misho 20026: errCnt += runOneSqlLine(p, zSql, p->in, startline); 1.4 misho 20027: nSql = 0; 20028: if( p->outCount ){ 20029: output_reset(p); 20030: p->outCount = 0; 1.5 ! misho 20031: }else{ ! 20032: clearTempFile(p); 1.4 misho 20033: } 20034: }else if( nSql && _all_whitespace(zSql) ){ 1.5 ! misho 20035: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); 1.2 misho 20036: nSql = 0; 20037: } 20038: } 1.5 ! misho 20039: if( nSql && !_all_whitespace(zSql) ){ ! 20040: errCnt += runOneSqlLine(p, zSql, p->in, startline); 1.2 misho 20041: } 1.4 misho 20042: free(zSql); 1.2 misho 20043: free(zLine); 1.3 misho 20044: return errCnt>0; 1.2 misho 20045: } 20046: 20047: /* 20048: ** Return a pathname which is the user's home directory. A 1.3 misho 20049: ** 0 return indicates an error of some kind. 1.2 misho 20050: */ 1.5 ! misho 20051: static char *find_home_dir(int clearFlag){ 1.3 misho 20052: static char *home_dir = NULL; 1.5 ! misho 20053: if( clearFlag ){ ! 20054: free(home_dir); ! 20055: home_dir = 0; ! 20056: return 0; ! 20057: } 1.3 misho 20058: if( home_dir ) return home_dir; 1.2 misho 20059: 1.4 misho 20060: #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ 20061: && !defined(__RTP__) && !defined(_WRS_KERNEL) 1.3 misho 20062: { 20063: struct passwd *pwent; 20064: uid_t uid = getuid(); 20065: if( (pwent=getpwuid(uid)) != NULL) { 20066: home_dir = pwent->pw_dir; 20067: } 1.2 misho 20068: } 20069: #endif 20070: 20071: #if defined(_WIN32_WCE) 20072: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() 20073: */ 1.3 misho 20074: home_dir = "/"; 1.2 misho 20075: #else 20076: 1.3 misho 20077: #if defined(_WIN32) || defined(WIN32) 1.2 misho 20078: if (!home_dir) { 20079: home_dir = getenv("USERPROFILE"); 20080: } 20081: #endif 20082: 20083: if (!home_dir) { 20084: home_dir = getenv("HOME"); 20085: } 20086: 1.3 misho 20087: #if defined(_WIN32) || defined(WIN32) 1.2 misho 20088: if (!home_dir) { 20089: char *zDrive, *zPath; 20090: int n; 20091: zDrive = getenv("HOMEDRIVE"); 20092: zPath = getenv("HOMEPATH"); 20093: if( zDrive && zPath ){ 20094: n = strlen30(zDrive) + strlen30(zPath) + 1; 20095: home_dir = malloc( n ); 20096: if( home_dir==0 ) return 0; 20097: sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); 20098: return home_dir; 20099: } 20100: home_dir = "c:\\"; 20101: } 20102: #endif 20103: 20104: #endif /* !_WIN32_WCE */ 20105: 20106: if( home_dir ){ 20107: int n = strlen30(home_dir) + 1; 20108: char *z = malloc( n ); 20109: if( z ) memcpy(z, home_dir, n); 20110: home_dir = z; 20111: } 20112: 20113: return home_dir; 20114: } 20115: 20116: /* 20117: ** Read input from the file given by sqliterc_override. Or if that 20118: ** parameter is NULL, take input from ~/.sqliterc 20119: ** 20120: ** Returns the number of errors. 20121: */ 1.4 misho 20122: static void process_sqliterc( 20123: ShellState *p, /* Configuration data */ 1.2 misho 20124: const char *sqliterc_override /* Name of config file. NULL to use default */ 20125: ){ 20126: char *home_dir = NULL; 20127: const char *sqliterc = sqliterc_override; 20128: char *zBuf = 0; 1.5 ! misho 20129: FILE *inSaved = p->in; ! 20130: int savedLineno = p->lineno; 1.2 misho 20131: 20132: if (sqliterc == NULL) { 1.5 ! misho 20133: home_dir = find_home_dir(0); 1.2 misho 20134: if( home_dir==0 ){ 1.4 misho 20135: raw_printf(stderr, "-- warning: cannot find home directory;" 20136: " cannot read ~/.sqliterc\n"); 20137: return; 1.2 misho 20138: } 1.3 misho 20139: zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); 20140: sqliterc = zBuf; 1.2 misho 20141: } 1.5 ! misho 20142: p->in = fopen(sqliterc,"rb"); ! 20143: if( p->in ){ 1.2 misho 20144: if( stdin_is_interactive ){ 1.4 misho 20145: utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); 1.2 misho 20146: } 1.5 ! misho 20147: process_input(p); ! 20148: fclose(p->in); 1.2 misho 20149: } 1.5 ! misho 20150: p->in = inSaved; ! 20151: p->lineno = savedLineno; 1.3 misho 20152: sqlite3_free(zBuf); 1.2 misho 20153: } 20154: 20155: /* 20156: ** Show available command line options 20157: */ 1.4 misho 20158: static const char zOptions[] = 1.5 ! misho 20159: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) ! 20160: " -A ARGS... run \".archive ARGS\" and exit\n" ! 20161: #endif ! 20162: " -append append the database to the end of the file\n" 1.4 misho 20163: " -ascii set output mode to 'ascii'\n" 1.2 misho 20164: " -bail stop after hitting an error\n" 20165: " -batch force batch I/O\n" 1.5 ! misho 20166: " -box set output mode to 'box'\n" 1.2 misho 20167: " -column set output mode to 'column'\n" 1.3 misho 20168: " -cmd COMMAND run \"COMMAND\" before reading stdin\n" 1.2 misho 20169: " -csv set output mode to 'csv'\n" 1.5 ! misho 20170: #if defined(SQLITE_ENABLE_DESERIALIZE) ! 20171: " -deserialize open the database using sqlite3_deserialize()\n" ! 20172: #endif 1.3 misho 20173: " -echo print commands before execution\n" 20174: " -init FILENAME read/process named file\n" 20175: " -[no]header turn headers on or off\n" 20176: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) 20177: " -heap SIZE Size of heap for memsys3 or memsys5\n" 20178: #endif 20179: " -help show this message\n" 1.2 misho 20180: " -html set output mode to HTML\n" 1.3 misho 20181: " -interactive force interactive I/O\n" 1.5 ! misho 20182: " -json set output mode to 'json'\n" 1.2 misho 20183: " -line set output mode to 'line'\n" 20184: " -list set output mode to 'list'\n" 1.4 misho 20185: " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" 1.5 ! misho 20186: " -markdown set output mode to 'markdown'\n" ! 20187: #if defined(SQLITE_ENABLE_DESERIALIZE) ! 20188: " -maxsize N maximum size for a --deserialize database\n" ! 20189: #endif ! 20190: " -memtrace trace all memory allocations and deallocations\n" 1.4 misho 20191: " -mmap N default mmap size set to N\n" 1.3 misho 20192: #ifdef SQLITE_ENABLE_MULTIPLEX 20193: " -multiplex enable the multiplexor VFS\n" 20194: #endif 1.4 misho 20195: " -newline SEP set output row separator. Default: '\\n'\n" 1.5 ! misho 20196: " -nofollow refuse to open symbolic links to database files\n" 1.3 misho 20197: " -nullvalue TEXT set text string for NULL values. Default ''\n" 1.4 misho 20198: " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" 1.5 ! misho 20199: " -quote set output mode to 'quote'\n" ! 20200: " -readonly open the database read-only\n" 1.4 misho 20201: " -separator SEP set output column separator. Default: '|'\n" 1.5 ! misho 20202: #ifdef SQLITE_ENABLE_SORTER_REFERENCES ! 20203: " -sorterref SIZE sorter references threshold size\n" ! 20204: #endif 1.2 misho 20205: " -stats print memory stats before each finalize\n" 1.5 ! misho 20206: " -table set output mode to 'table'\n" 1.2 misho 20207: " -version show SQLite version\n" 20208: " -vfs NAME use NAME as the default VFS\n" 20209: #ifdef SQLITE_ENABLE_VFSTRACE 20210: " -vfstrace enable tracing of all VFS calls\n" 20211: #endif 1.5 ! misho 20212: #ifdef SQLITE_HAVE_ZLIB ! 20213: " -zip open the file as a ZIP Archive\n" ! 20214: #endif 1.2 misho 20215: ; 20216: static void usage(int showDetail){ 1.4 misho 20217: utf8_printf(stderr, 20218: "Usage: %s [OPTIONS] FILENAME [SQL]\n" 1.2 misho 20219: "FILENAME is the name of an SQLite database. A new database is created\n" 20220: "if the file does not previously exist.\n", Argv0); 20221: if( showDetail ){ 1.4 misho 20222: utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); 1.2 misho 20223: }else{ 1.4 misho 20224: raw_printf(stderr, "Use the -help option for additional information\n"); 1.2 misho 20225: } 20226: exit(1); 20227: } 20228: 20229: /* 1.5 ! misho 20230: ** Internal check: Verify that the SQLite is uninitialized. Print a ! 20231: ** error message if it is initialized. ! 20232: */ ! 20233: static void verify_uninitialized(void){ ! 20234: if( sqlite3_config(-1)==SQLITE_MISUSE ){ ! 20235: utf8_printf(stdout, "WARNING: attempt to configure SQLite after" ! 20236: " initialization.\n"); ! 20237: } ! 20238: } ! 20239: ! 20240: /* 1.2 misho 20241: ** Initialize the state information in data 20242: */ 1.4 misho 20243: static void main_init(ShellState *data) { 1.2 misho 20244: memset(data, 0, sizeof(*data)); 1.4 misho 20245: data->normalMode = data->cMode = data->mode = MODE_List; 20246: data->autoExplain = 1; 20247: memcpy(data->colSeparator,SEP_Column, 2); 20248: memcpy(data->rowSeparator,SEP_Row, 2); 1.2 misho 20249: data->showHeader = 0; 1.4 misho 20250: data->shellFlgs = SHFLG_Lookaside; 1.5 ! misho 20251: verify_uninitialized(); 1.2 misho 20252: sqlite3_config(SQLITE_CONFIG_URI, 1); 20253: sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); 1.4 misho 20254: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); 1.2 misho 20255: sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); 20256: sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); 20257: } 20258: 1.3 misho 20259: /* 1.4 misho 20260: ** Output text to the console in a font that attracts extra attention. 20261: */ 20262: #ifdef _WIN32 20263: static void printBold(const char *zText){ 1.5 ! misho 20264: #if !SQLITE_OS_WINRT 1.4 misho 20265: HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); 20266: CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; 20267: GetConsoleScreenBufferInfo(out, &defaultScreenInfo); 20268: SetConsoleTextAttribute(out, 20269: FOREGROUND_RED|FOREGROUND_INTENSITY 20270: ); 1.5 ! misho 20271: #endif 1.4 misho 20272: printf("%s", zText); 1.5 ! misho 20273: #if !SQLITE_OS_WINRT 1.4 misho 20274: SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); 1.5 ! misho 20275: #endif 1.4 misho 20276: } 20277: #else 20278: static void printBold(const char *zText){ 20279: printf("\033[1m%s\033[0m", zText); 20280: } 20281: #endif 20282: 20283: /* 1.3 misho 20284: ** Get the argument to an --option. Throw an error and die if no argument 20285: ** is available. 20286: */ 20287: static char *cmdline_option_value(int argc, char **argv, int i){ 20288: if( i==argc ){ 1.4 misho 20289: utf8_printf(stderr, "%s: Error: missing argument to %s\n", 1.3 misho 20290: argv[0], argv[argc-1]); 20291: exit(1); 20292: } 20293: return argv[i]; 20294: } 20295: 1.4 misho 20296: #ifndef SQLITE_SHELL_IS_UTF8 20297: # if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 20298: # define SQLITE_SHELL_IS_UTF8 (0) 20299: # else 20300: # define SQLITE_SHELL_IS_UTF8 (1) 20301: # endif 20302: #endif 20303: 20304: #if SQLITE_SHELL_IS_UTF8 20305: int SQLITE_CDECL main(int argc, char **argv){ 20306: #else 20307: int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ 20308: char **argv; 20309: #endif 1.2 misho 20310: char *zErrMsg = 0; 1.4 misho 20311: ShellState data; 1.2 misho 20312: const char *zInitFile = 0; 20313: int i; 20314: int rc = 0; 1.4 misho 20315: int warnInmemoryDb = 0; 20316: int readStdin = 1; 20317: int nCmd = 0; 20318: char **azCmd = 0; 1.5 ! misho 20319: const char *zVfs = 0; /* Value of -vfs command-line option */ ! 20320: #if !SQLITE_SHELL_IS_UTF8 ! 20321: char **argvToFree = 0; ! 20322: int argcToFree = 0; ! 20323: #endif 1.4 misho 20324: 20325: setBinaryMode(stdin, 0); 20326: setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ 20327: stdin_is_interactive = isatty(0); 20328: stdout_is_console = isatty(1); 1.2 misho 20329: 1.5 ! misho 20330: #ifdef SQLITE_DEBUG ! 20331: registerOomSimulator(); ! 20332: #endif ! 20333: ! 20334: #if !defined(_WIN32_WCE) ! 20335: if( getenv("SQLITE_DEBUG_BREAK") ){ ! 20336: if( isatty(0) && isatty(2) ){ ! 20337: fprintf(stderr, ! 20338: "attach debugger to process %d and press any key to continue.\n", ! 20339: GETPID()); ! 20340: fgetc(stdin); ! 20341: }else{ ! 20342: #if defined(_WIN32) || defined(WIN32) ! 20343: #if SQLITE_OS_WINRT ! 20344: __debugbreak(); ! 20345: #else ! 20346: DebugBreak(); ! 20347: #endif ! 20348: #elif defined(SIGTRAP) ! 20349: raise(SIGTRAP); ! 20350: #endif ! 20351: } ! 20352: } ! 20353: #endif ! 20354: 1.4 misho 20355: #if USE_SYSTEM_SQLITE+0!=1 1.5 ! misho 20356: if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ 1.4 misho 20357: utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", 1.2 misho 20358: sqlite3_sourceid(), SQLITE_SOURCE_ID); 20359: exit(1); 20360: } 1.4 misho 20361: #endif 20362: main_init(&data); 1.5 ! misho 20363: ! 20364: /* On Windows, we must translate command-line arguments into UTF-8. ! 20365: ** The SQLite memory allocator subsystem has to be enabled in order to ! 20366: ** do this. But we want to run an sqlite3_shutdown() afterwards so that ! 20367: ** subsequent sqlite3_config() calls will work. So copy all results into ! 20368: ** memory that does not come from the SQLite memory allocator. ! 20369: */ 1.4 misho 20370: #if !SQLITE_SHELL_IS_UTF8 20371: sqlite3_initialize(); 1.5 ! misho 20372: argvToFree = malloc(sizeof(argv[0])*argc*2); ! 20373: argcToFree = argc; ! 20374: argv = argvToFree + argc; ! 20375: if( argv==0 ) shell_out_of_memory(); 1.4 misho 20376: for(i=0; i<argc; i++){ 1.5 ! misho 20377: char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); ! 20378: int n; ! 20379: if( z==0 ) shell_out_of_memory(); ! 20380: n = (int)strlen(z); ! 20381: argv[i] = malloc( n+1 ); ! 20382: if( argv[i]==0 ) shell_out_of_memory(); ! 20383: memcpy(argv[i], z, n+1); ! 20384: argvToFree[i] = argv[i]; ! 20385: sqlite3_free(z); 1.4 misho 20386: } 1.5 ! misho 20387: sqlite3_shutdown(); 1.4 misho 20388: #endif 1.5 ! misho 20389: 1.4 misho 20390: assert( argc>=1 && argv && argv[0] ); 1.2 misho 20391: Argv0 = argv[0]; 20392: 20393: /* Make sure we have a valid signal handler early, before anything 20394: ** else is done. 20395: */ 20396: #ifdef SIGINT 20397: signal(SIGINT, interrupt_handler); 1.5 ! misho 20398: #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) ! 20399: SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); 1.2 misho 20400: #endif 20401: 1.4 misho 20402: #ifdef SQLITE_SHELL_DBNAME_PROC 20403: { 20404: /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name 20405: ** of a C-function that will provide the name of the database file. Use 20406: ** this compile-time option to embed this shell program in larger 20407: ** applications. */ 20408: extern void SQLITE_SHELL_DBNAME_PROC(const char**); 20409: SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename); 20410: warnInmemoryDb = 0; 20411: } 20412: #endif 20413: 1.2 misho 20414: /* Do an initial pass through the command-line argument to locate 20415: ** the name of the database file, the name of the initialization file, 20416: ** the size of the alternative malloc heap, 20417: ** and the first command to execute. 20418: */ 1.5 ! misho 20419: verify_uninitialized(); 1.3 misho 20420: for(i=1; i<argc; i++){ 1.2 misho 20421: char *z; 20422: z = argv[i]; 1.3 misho 20423: if( z[0]!='-' ){ 20424: if( data.zDbFilename==0 ){ 20425: data.zDbFilename = z; 1.4 misho 20426: }else{ 20427: /* Excesss arguments are interpreted as SQL (or dot-commands) and 20428: ** mean that nothing is read from stdin */ 20429: readStdin = 0; 20430: nCmd++; 20431: azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); 1.5 ! misho 20432: if( azCmd==0 ) shell_out_of_memory(); 1.4 misho 20433: azCmd[nCmd-1] = z; 1.3 misho 20434: } 20435: } 20436: if( z[1]=='-' ) z++; 20437: if( strcmp(z,"-separator")==0 20438: || strcmp(z,"-nullvalue")==0 1.4 misho 20439: || strcmp(z,"-newline")==0 1.3 misho 20440: || strcmp(z,"-cmd")==0 20441: ){ 20442: (void)cmdline_option_value(argc, argv, ++i); 20443: }else if( strcmp(z,"-init")==0 ){ 20444: zInitFile = cmdline_option_value(argc, argv, ++i); 20445: }else if( strcmp(z,"-batch")==0 ){ 20446: /* Need to check for batch mode here to so we can avoid printing 1.4 misho 20447: ** informational messages (like from process_sqliterc) before 1.3 misho 20448: ** we do the actual processing of arguments later in a second pass. 20449: */ 1.2 misho 20450: stdin_is_interactive = 0; 1.3 misho 20451: }else if( strcmp(z,"-heap")==0 ){ 1.2 misho 20452: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) 20453: const char *zSize; 20454: sqlite3_int64 szHeap; 20455: 1.3 misho 20456: zSize = cmdline_option_value(argc, argv, ++i); 1.4 misho 20457: szHeap = integerValue(zSize); 1.2 misho 20458: if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; 20459: sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); 1.4 misho 20460: #else 20461: (void)cmdline_option_value(argc, argv, ++i); 1.2 misho 20462: #endif 1.4 misho 20463: }else if( strcmp(z,"-pagecache")==0 ){ 20464: int n, sz; 20465: sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); 20466: if( sz>70000 ) sz = 70000; 20467: if( sz<0 ) sz = 0; 20468: n = (int)integerValue(cmdline_option_value(argc,argv,++i)); 20469: sqlite3_config(SQLITE_CONFIG_PAGECACHE, 20470: (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n); 20471: data.shellFlgs |= SHFLG_Pagecache; 20472: }else if( strcmp(z,"-lookaside")==0 ){ 20473: int n, sz; 20474: sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); 20475: if( sz<0 ) sz = 0; 20476: n = (int)integerValue(cmdline_option_value(argc,argv,++i)); 20477: if( n<0 ) n = 0; 20478: sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); 20479: if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; 1.2 misho 20480: #ifdef SQLITE_ENABLE_VFSTRACE 1.3 misho 20481: }else if( strcmp(z,"-vfstrace")==0 ){ 1.2 misho 20482: extern int vfstrace_register( 20483: const char *zTraceName, 20484: const char *zOldVfsName, 20485: int (*xOut)(const char*,void*), 20486: void *pOutArg, 20487: int makeDefault 20488: ); 20489: vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); 20490: #endif 20491: #ifdef SQLITE_ENABLE_MULTIPLEX 1.3 misho 20492: }else if( strcmp(z,"-multiplex")==0 ){ 1.2 misho 20493: extern int sqlite3_multiple_initialize(const char*,int); 20494: sqlite3_multiplex_initialize(0, 1); 20495: #endif 1.4 misho 20496: }else if( strcmp(z,"-mmap")==0 ){ 20497: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); 20498: sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); 1.5 ! misho 20499: #ifdef SQLITE_ENABLE_SORTER_REFERENCES ! 20500: }else if( strcmp(z,"-sorterref")==0 ){ ! 20501: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); ! 20502: sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz); ! 20503: #endif 1.3 misho 20504: }else if( strcmp(z,"-vfs")==0 ){ 1.5 ! misho 20505: zVfs = cmdline_option_value(argc, argv, ++i); ! 20506: #ifdef SQLITE_HAVE_ZLIB ! 20507: }else if( strcmp(z,"-zip")==0 ){ ! 20508: data.openMode = SHELL_OPEN_ZIPFILE; ! 20509: #endif ! 20510: }else if( strcmp(z,"-append")==0 ){ ! 20511: data.openMode = SHELL_OPEN_APPENDVFS; ! 20512: #ifdef SQLITE_ENABLE_DESERIALIZE ! 20513: }else if( strcmp(z,"-deserialize")==0 ){ ! 20514: data.openMode = SHELL_OPEN_DESERIALIZE; ! 20515: }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){ ! 20516: data.szMax = integerValue(argv[++i]); ! 20517: #endif ! 20518: }else if( strcmp(z,"-readonly")==0 ){ ! 20519: data.openMode = SHELL_OPEN_READONLY; ! 20520: }else if( strcmp(z,"-nofollow")==0 ){ ! 20521: data.openFlags = SQLITE_OPEN_NOFOLLOW; ! 20522: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ! 20523: }else if( strncmp(z, "-A",2)==0 ){ ! 20524: /* All remaining command-line arguments are passed to the ".archive" ! 20525: ** command, so ignore them */ ! 20526: break; ! 20527: #endif ! 20528: }else if( strcmp(z, "-memtrace")==0 ){ ! 20529: sqlite3MemTraceActivate(stderr); ! 20530: } ! 20531: } ! 20532: verify_uninitialized(); ! 20533: ! 20534: ! 20535: #ifdef SQLITE_SHELL_INIT_PROC ! 20536: { ! 20537: /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name ! 20538: ** of a C-function that will perform initialization actions on SQLite that ! 20539: ** occur just before or after sqlite3_initialize(). Use this compile-time ! 20540: ** option to embed this shell program in larger applications. */ ! 20541: extern void SQLITE_SHELL_INIT_PROC(void); ! 20542: SQLITE_SHELL_INIT_PROC(); ! 20543: } ! 20544: #else ! 20545: /* All the sqlite3_config() calls have now been made. So it is safe ! 20546: ** to call sqlite3_initialize() and process any command line -vfs option. */ ! 20547: sqlite3_initialize(); ! 20548: #endif ! 20549: ! 20550: if( zVfs ){ ! 20551: sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); ! 20552: if( pVfs ){ ! 20553: sqlite3_vfs_register(pVfs, 1); ! 20554: }else{ ! 20555: utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); ! 20556: exit(1); 1.2 misho 20557: } 20558: } 1.5 ! misho 20559: 1.3 misho 20560: if( data.zDbFilename==0 ){ 1.2 misho 20561: #ifndef SQLITE_OMIT_MEMORYDB 20562: data.zDbFilename = ":memory:"; 1.4 misho 20563: warnInmemoryDb = argc==1; 1.2 misho 20564: #else 1.4 misho 20565: utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); 1.3 misho 20566: return 1; 1.2 misho 20567: #endif 20568: } 20569: data.out = stdout; 1.5 ! misho 20570: sqlite3_appendvfs_init(0,0,0); 1.2 misho 20571: 20572: /* Go ahead and open the database file if it already exists. If the 20573: ** file does not exist, delay opening it. This prevents empty database 20574: ** files from being created if a user mistypes the database name argument 20575: ** to the sqlite command-line tool. 20576: */ 20577: if( access(data.zDbFilename, 0)==0 ){ 1.4 misho 20578: open_db(&data, 0); 1.2 misho 20579: } 20580: 20581: /* Process the initialization file if there is one. If no -init option 20582: ** is given on the command line, look for a file named ~/.sqliterc and 20583: ** try to process it. 20584: */ 1.4 misho 20585: process_sqliterc(&data,zInitFile); 1.2 misho 20586: 20587: /* Make a second pass through the command-line argument and set 20588: ** options. This second pass is delayed until after the initialization 20589: ** file is processed so that the command-line arguments will override 20590: ** settings in the initialization file. 20591: */ 1.3 misho 20592: for(i=1; i<argc; i++){ 1.2 misho 20593: char *z = argv[i]; 1.3 misho 20594: if( z[0]!='-' ) continue; 1.2 misho 20595: if( z[1]=='-' ){ z++; } 20596: if( strcmp(z,"-init")==0 ){ 20597: i++; 20598: }else if( strcmp(z,"-html")==0 ){ 20599: data.mode = MODE_Html; 20600: }else if( strcmp(z,"-list")==0 ){ 20601: data.mode = MODE_List; 1.5 ! misho 20602: }else if( strcmp(z,"-quote")==0 ){ ! 20603: data.mode = MODE_Quote; 1.2 misho 20604: }else if( strcmp(z,"-line")==0 ){ 20605: data.mode = MODE_Line; 20606: }else if( strcmp(z,"-column")==0 ){ 20607: data.mode = MODE_Column; 1.5 ! misho 20608: }else if( strcmp(z,"-json")==0 ){ ! 20609: data.mode = MODE_Json; ! 20610: }else if( strcmp(z,"-markdown")==0 ){ ! 20611: data.mode = MODE_Markdown; ! 20612: }else if( strcmp(z,"-table")==0 ){ ! 20613: data.mode = MODE_Table; ! 20614: }else if( strcmp(z,"-box")==0 ){ ! 20615: data.mode = MODE_Box; 1.2 misho 20616: }else if( strcmp(z,"-csv")==0 ){ 20617: data.mode = MODE_Csv; 1.4 misho 20618: memcpy(data.colSeparator,",",2); 1.5 ! misho 20619: #ifdef SQLITE_HAVE_ZLIB ! 20620: }else if( strcmp(z,"-zip")==0 ){ ! 20621: data.openMode = SHELL_OPEN_ZIPFILE; ! 20622: #endif ! 20623: }else if( strcmp(z,"-append")==0 ){ ! 20624: data.openMode = SHELL_OPEN_APPENDVFS; ! 20625: #ifdef SQLITE_ENABLE_DESERIALIZE ! 20626: }else if( strcmp(z,"-deserialize")==0 ){ ! 20627: data.openMode = SHELL_OPEN_DESERIALIZE; ! 20628: }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){ ! 20629: data.szMax = integerValue(argv[++i]); ! 20630: #endif ! 20631: }else if( strcmp(z,"-readonly")==0 ){ ! 20632: data.openMode = SHELL_OPEN_READONLY; ! 20633: }else if( strcmp(z,"-nofollow")==0 ){ ! 20634: data.openFlags |= SQLITE_OPEN_NOFOLLOW; 1.4 misho 20635: }else if( strcmp(z,"-ascii")==0 ){ 20636: data.mode = MODE_Ascii; 20637: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, 20638: SEP_Unit); 20639: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, 20640: SEP_Record); 1.2 misho 20641: }else if( strcmp(z,"-separator")==0 ){ 1.4 misho 20642: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, 20643: "%s",cmdline_option_value(argc,argv,++i)); 20644: }else if( strcmp(z,"-newline")==0 ){ 20645: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, 1.3 misho 20646: "%s",cmdline_option_value(argc,argv,++i)); 1.2 misho 20647: }else if( strcmp(z,"-nullvalue")==0 ){ 1.4 misho 20648: sqlite3_snprintf(sizeof(data.nullValue), data.nullValue, 1.3 misho 20649: "%s",cmdline_option_value(argc,argv,++i)); 1.2 misho 20650: }else if( strcmp(z,"-header")==0 ){ 20651: data.showHeader = 1; 20652: }else if( strcmp(z,"-noheader")==0 ){ 20653: data.showHeader = 0; 20654: }else if( strcmp(z,"-echo")==0 ){ 1.5 ! misho 20655: ShellSetFlag(&data, SHFLG_Echo); 1.4 misho 20656: }else if( strcmp(z,"-eqp")==0 ){ 1.5 ! misho 20657: data.autoEQP = AUTOEQP_on; 1.4 misho 20658: }else if( strcmp(z,"-eqpfull")==0 ){ 1.5 ! misho 20659: data.autoEQP = AUTOEQP_full; 1.2 misho 20660: }else if( strcmp(z,"-stats")==0 ){ 20661: data.statsOn = 1; 1.4 misho 20662: }else if( strcmp(z,"-scanstats")==0 ){ 20663: data.scanstatsOn = 1; 20664: }else if( strcmp(z,"-backslash")==0 ){ 20665: /* Undocumented command-line option: -backslash 20666: ** Causes C-style backslash escapes to be evaluated in SQL statements 20667: ** prior to sending the SQL into SQLite. Useful for injecting 20668: ** crazy bytes in the middle of SQL statements for testing and debugging. 20669: */ 1.5 ! misho 20670: ShellSetFlag(&data, SHFLG_Backslash); 1.2 misho 20671: }else if( strcmp(z,"-bail")==0 ){ 20672: bail_on_error = 1; 20673: }else if( strcmp(z,"-version")==0 ){ 20674: printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); 20675: return 0; 20676: }else if( strcmp(z,"-interactive")==0 ){ 20677: stdin_is_interactive = 1; 20678: }else if( strcmp(z,"-batch")==0 ){ 20679: stdin_is_interactive = 0; 20680: }else if( strcmp(z,"-heap")==0 ){ 20681: i++; 1.4 misho 20682: }else if( strcmp(z,"-pagecache")==0 ){ 20683: i+=2; 20684: }else if( strcmp(z,"-lookaside")==0 ){ 20685: i+=2; 20686: }else if( strcmp(z,"-mmap")==0 ){ 20687: i++; 1.5 ! misho 20688: }else if( strcmp(z,"-memtrace")==0 ){ ! 20689: i++; ! 20690: #ifdef SQLITE_ENABLE_SORTER_REFERENCES ! 20691: }else if( strcmp(z,"-sorterref")==0 ){ ! 20692: i++; ! 20693: #endif 1.2 misho 20694: }else if( strcmp(z,"-vfs")==0 ){ 20695: i++; 20696: #ifdef SQLITE_ENABLE_VFSTRACE 20697: }else if( strcmp(z,"-vfstrace")==0 ){ 20698: i++; 20699: #endif 20700: #ifdef SQLITE_ENABLE_MULTIPLEX 20701: }else if( strcmp(z,"-multiplex")==0 ){ 20702: i++; 20703: #endif 1.3 misho 20704: }else if( strcmp(z,"-help")==0 ){ 1.2 misho 20705: usage(1); 1.3 misho 20706: }else if( strcmp(z,"-cmd")==0 ){ 1.4 misho 20707: /* Run commands that follow -cmd first and separately from commands 20708: ** that simply appear on the command-line. This seems goofy. It would 20709: ** be better if all commands ran in the order that they appear. But 20710: ** we retain the goofy behavior for historical compatibility. */ 1.3 misho 20711: if( i==argc-1 ) break; 20712: z = cmdline_option_value(argc,argv,++i); 20713: if( z[0]=='.' ){ 20714: rc = do_meta_command(z, &data); 1.4 misho 20715: if( rc && bail_on_error ) return rc==2 ? 0 : rc; 1.3 misho 20716: }else{ 1.4 misho 20717: open_db(&data, 0); 1.5 ! misho 20718: rc = shell_exec(&data, z, &zErrMsg); 1.3 misho 20719: if( zErrMsg!=0 ){ 1.4 misho 20720: utf8_printf(stderr,"Error: %s\n", zErrMsg); 1.3 misho 20721: if( bail_on_error ) return rc!=0 ? rc : 1; 20722: }else if( rc!=0 ){ 1.4 misho 20723: utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z); 1.3 misho 20724: if( bail_on_error ) return rc; 20725: } 20726: } 1.5 ! misho 20727: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ! 20728: }else if( strncmp(z, "-A", 2)==0 ){ ! 20729: if( nCmd>0 ){ ! 20730: utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands" ! 20731: " with \"%s\"\n", z); ! 20732: return 1; ! 20733: } ! 20734: open_db(&data, OPEN_DB_ZIPFILE); ! 20735: if( z[2] ){ ! 20736: argv[i] = &z[2]; ! 20737: arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); ! 20738: }else{ ! 20739: arDotCommand(&data, 1, argv+i, argc-i); ! 20740: } ! 20741: readStdin = 0; ! 20742: break; ! 20743: #endif 1.2 misho 20744: }else{ 1.4 misho 20745: utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); 20746: raw_printf(stderr,"Use -help for a list of options.\n"); 1.2 misho 20747: return 1; 20748: } 1.4 misho 20749: data.cMode = data.mode; 1.2 misho 20750: } 20751: 1.4 misho 20752: if( !readStdin ){ 20753: /* Run all arguments that do not begin with '-' as if they were separate 20754: ** command-line inputs, except for the argToSkip argument which contains 20755: ** the database filename. 1.2 misho 20756: */ 1.4 misho 20757: for(i=0; i<nCmd; i++){ 20758: if( azCmd[i][0]=='.' ){ 20759: rc = do_meta_command(azCmd[i], &data); 20760: if( rc ) return rc==2 ? 0 : rc; 20761: }else{ 20762: open_db(&data, 0); 1.5 ! misho 20763: rc = shell_exec(&data, azCmd[i], &zErrMsg); 1.4 misho 20764: if( zErrMsg!=0 ){ 20765: utf8_printf(stderr,"Error: %s\n", zErrMsg); 20766: return rc!=0 ? rc : 1; 20767: }else if( rc!=0 ){ 20768: utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]); 20769: return rc; 20770: } 1.2 misho 20771: } 20772: } 1.4 misho 20773: free(azCmd); 1.2 misho 20774: }else{ 20775: /* Run commands received from standard input 20776: */ 20777: if( stdin_is_interactive ){ 20778: char *zHome; 1.5 ! misho 20779: char *zHistory; 1.2 misho 20780: int nHistory; 20781: printf( 20782: "SQLite version %s %.19s\n" /*extra-version-info*/ 1.4 misho 20783: "Enter \".help\" for usage hints.\n", 1.2 misho 20784: sqlite3_libversion(), sqlite3_sourceid() 20785: ); 1.4 misho 20786: if( warnInmemoryDb ){ 20787: printf("Connected to a "); 20788: printBold("transient in-memory database"); 20789: printf(".\nUse \".open FILENAME\" to reopen on a " 20790: "persistent database.\n"); 20791: } 1.5 ! misho 20792: zHistory = getenv("SQLITE_HISTORY"); ! 20793: if( zHistory ){ ! 20794: zHistory = strdup(zHistory); ! 20795: }else if( (zHome = find_home_dir(0))!=0 ){ 1.2 misho 20796: nHistory = strlen30(zHome) + 20; 20797: if( (zHistory = malloc(nHistory))!=0 ){ 20798: sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); 20799: } 20800: } 1.4 misho 20801: if( zHistory ){ shell_read_history(zHistory); } 1.5 ! misho 20802: #if HAVE_READLINE || HAVE_EDITLINE ! 20803: rl_attempted_completion_function = readline_completion; ! 20804: #elif HAVE_LINENOISE ! 20805: linenoiseSetCompletionCallback(linenoise_completion); ! 20806: #endif ! 20807: data.in = 0; ! 20808: rc = process_input(&data); 1.2 misho 20809: if( zHistory ){ 1.5 ! misho 20810: shell_stifle_history(2000); 1.4 misho 20811: shell_write_history(zHistory); 1.2 misho 20812: free(zHistory); 20813: } 20814: }else{ 1.5 ! misho 20815: data.in = stdin; ! 20816: rc = process_input(&data); 1.2 misho 20817: } 20818: } 20819: set_table_name(&data, 0); 20820: if( data.db ){ 1.4 misho 20821: session_close_all(&data); 1.5 ! misho 20822: close_db(data.db); 1.2 misho 20823: } 1.4 misho 20824: sqlite3_free(data.zFreeOnClose); 1.5 ! misho 20825: find_home_dir(1); ! 20826: output_reset(&data); ! 20827: data.doXdgOpen = 0; ! 20828: clearTempFile(&data); 1.4 misho 20829: #if !SQLITE_SHELL_IS_UTF8 1.5 ! misho 20830: for(i=0; i<argcToFree; i++) free(argvToFree[i]); ! 20831: free(argvToFree); 1.4 misho 20832: #endif 1.5 ! misho 20833: free(data.colWidth); ! 20834: /* Clear the global data structure so that valgrind will detect memory ! 20835: ** leaks */ ! 20836: memset(&data, 0, sizeof(data)); 1.2 misho 20837: return rc; 20838: }