Annotation of elwix/files/sqlite/dist/shell.c, revision 1.5
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>