Annotation of elwix/files/sqlite/dist/shell.c, revision 1.4.2.2
1.4.2.2 ! 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.4.2.2 ! misho 39: ** Warning pragmas copied from msvc.h in the core.
1.4 misho 40: */
1.4.2.2 ! misho 41: #if defined(_MSC_VER)
! 42: #pragma warning(disable : 4054)
! 43: #pragma warning(disable : 4055)
! 44: #pragma warning(disable : 4100)
! 45: #pragma warning(disable : 4127)
! 46: #pragma warning(disable : 4130)
! 47: #pragma warning(disable : 4152)
! 48: #pragma warning(disable : 4189)
! 49: #pragma warning(disable : 4206)
! 50: #pragma warning(disable : 4210)
! 51: #pragma warning(disable : 4232)
! 52: #pragma warning(disable : 4244)
! 53: #pragma warning(disable : 4305)
! 54: #pragma warning(disable : 4306)
! 55: #pragma warning(disable : 4702)
! 56: #pragma warning(disable : 4706)
! 57: #endif /* defined(_MSC_VER) */
1.4 misho 58:
59: /*
60: ** No support for loadable extensions in VxWorks.
61: */
62: #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
63: # define SQLITE_OMIT_LOAD_EXTENSION 1
64: #endif
65:
66: /*
1.2 misho 67: ** Enable large-file support for fopen() and friends on unix.
68: */
69: #ifndef SQLITE_DISABLE_LFS
70: # define _LARGE_FILE 1
71: # ifndef _FILE_OFFSET_BITS
72: # define _FILE_OFFSET_BITS 64
73: # endif
74: # define _LARGEFILE_SOURCE 1
75: #endif
76:
77: #include <stdlib.h>
78: #include <string.h>
79: #include <stdio.h>
80: #include <assert.h>
81: #include "sqlite3.h"
1.4.2.2 ! misho 82: typedef sqlite3_int64 i64;
! 83: typedef sqlite3_uint64 u64;
! 84: typedef unsigned char u8;
1.4 misho 85: #if SQLITE_USER_AUTHENTICATION
86: # include "sqlite3userauth.h"
87: #endif
1.2 misho 88: #include <ctype.h>
89: #include <stdarg.h>
90:
1.3 misho 91: #if !defined(_WIN32) && !defined(WIN32)
1.2 misho 92: # include <signal.h>
93: # if !defined(__RTP__) && !defined(_WRS_KERNEL)
94: # include <pwd.h>
95: # endif
1.4.2.2 ! misho 96: #endif
! 97: #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
1.2 misho 98: # include <unistd.h>
1.4.2.2 ! misho 99: # include <dirent.h>
! 100: # define GETPID getpid
! 101: # if defined(__MINGW32__)
! 102: # define DIRENT dirent
! 103: # ifndef S_ISLNK
! 104: # define S_ISLNK(mode) (0)
! 105: # endif
! 106: # endif
! 107: #else
! 108: # define GETPID (int)GetCurrentProcessId
1.2 misho 109: #endif
1.4.2.2 ! misho 110: #include <sys/types.h>
! 111: #include <sys/stat.h>
1.2 misho 112:
1.4 misho 113: #if HAVE_READLINE
1.2 misho 114: # include <readline/readline.h>
115: # include <readline/history.h>
116: #endif
1.4 misho 117:
118: #if HAVE_EDITLINE
119: # include <editline/readline.h>
120: #endif
121:
122: #if HAVE_EDITLINE || HAVE_READLINE
123:
124: # define shell_add_history(X) add_history(X)
125: # define shell_read_history(X) read_history(X)
126: # define shell_write_history(X) write_history(X)
127: # define shell_stifle_history(X) stifle_history(X)
128: # define shell_readline(X) readline(X)
129:
130: #elif HAVE_LINENOISE
131:
132: # include "linenoise.h"
133: # define shell_add_history(X) linenoiseHistoryAdd(X)
134: # define shell_read_history(X) linenoiseHistoryLoad(X)
135: # define shell_write_history(X) linenoiseHistorySave(X)
136: # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
137: # define shell_readline(X) linenoise(X)
138:
139: #else
140:
141: # define shell_read_history(X)
142: # define shell_write_history(X)
143: # define shell_stifle_history(X)
144:
145: # define SHELL_USE_LOCAL_GETLINE 1
1.2 misho 146: #endif
147:
1.4 misho 148:
1.2 misho 149: #if defined(_WIN32) || defined(WIN32)
150: # include <io.h>
1.4 misho 151: # include <fcntl.h>
152: # define isatty(h) _isatty(h)
153: # ifndef access
154: # define access(f,m) _access((f),(m))
155: # endif
1.4.2.2 ! misho 156: # ifndef unlink
! 157: # define unlink _unlink
! 158: # endif
! 159: # ifndef strdup
! 160: # define strdup _strdup
! 161: # endif
1.4 misho 162: # undef popen
163: # define popen _popen
164: # undef pclose
165: # define pclose _pclose
1.2 misho 166: #else
1.4 misho 167: /* Make sure isatty() has a prototype. */
168: extern int isatty(int);
169:
170: # if !defined(__RTP__) && !defined(_WRS_KERNEL)
171: /* popen and pclose are not C89 functions and so are
172: ** sometimes omitted from the <stdio.h> header */
173: extern FILE *popen(const char*,const char*);
174: extern int pclose(FILE*);
175: # else
176: # define SQLITE_OMIT_POPEN 1
177: # endif
1.2 misho 178: #endif
179:
180: #if defined(_WIN32_WCE)
181: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
182: * thus we always assume that we have a console. That can be
183: * overridden with the -batch command line option.
184: */
185: #define isatty(x) 1
186: #endif
187:
188: /* ctype macros that work with signed characters */
189: #define IsSpace(X) isspace((unsigned char)X)
190: #define IsDigit(X) isdigit((unsigned char)X)
191: #define ToLower(X) (char)tolower((unsigned char)X)
192:
1.4 misho 193: #if defined(_WIN32) || defined(WIN32)
194: #include <windows.h>
195:
196: /* string conversion routines only needed on Win32 */
197: extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
198: extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
199: extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
1.4.2.1 misho 200: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
1.4 misho 201: #endif
202:
203: /* On Windows, we normally run with output mode of TEXT so that \n characters
204: ** are automatically translated into \r\n. However, this behavior needs
205: ** to be disabled in some cases (ex: when generating CSV output and when
206: ** rendering quoted strings that contain \n characters). The following
207: ** routines take care of that.
208: */
209: #if defined(_WIN32) || defined(WIN32)
210: static void setBinaryMode(FILE *file, int isOutput){
211: if( isOutput ) fflush(file);
212: _setmode(_fileno(file), _O_BINARY);
213: }
214: static void setTextMode(FILE *file, int isOutput){
215: if( isOutput ) fflush(file);
216: _setmode(_fileno(file), _O_TEXT);
217: }
218: #else
219: # define setBinaryMode(X,Y)
220: # define setTextMode(X,Y)
221: #endif
222:
223:
224: /* True if the timer is enabled */
225: static int enableTimer = 0;
226:
227: /* Return the current wall-clock time */
228: static sqlite3_int64 timeOfDay(void){
229: static sqlite3_vfs *clockVfs = 0;
230: sqlite3_int64 t;
231: if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
232: if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
233: clockVfs->xCurrentTimeInt64(clockVfs, &t);
234: }else{
235: double r;
236: clockVfs->xCurrentTime(clockVfs, &r);
237: t = (sqlite3_int64)(r*86400000.0);
238: }
239: return t;
240: }
241:
242: #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
1.2 misho 243: #include <sys/time.h>
244: #include <sys/resource.h>
245:
1.4 misho 246: /* VxWorks does not support getrusage() as far as we can determine */
247: #if defined(_WRS_KERNEL) || defined(__RTP__)
248: struct rusage {
249: struct timeval ru_utime; /* user CPU time used */
250: struct timeval ru_stime; /* system CPU time used */
251: };
252: #define getrusage(A,B) memset(B,0,sizeof(*B))
253: #endif
254:
1.2 misho 255: /* Saved resource information for the beginning of an operation */
1.4 misho 256: static struct rusage sBegin; /* CPU time at start */
257: static sqlite3_int64 iBegin; /* Wall-clock time at start */
1.2 misho 258:
259: /*
260: ** Begin timing an operation
261: */
262: static void beginTimer(void){
263: if( enableTimer ){
264: getrusage(RUSAGE_SELF, &sBegin);
1.4 misho 265: iBegin = timeOfDay();
1.2 misho 266: }
267: }
268:
269: /* Return the difference of two time_structs in seconds */
270: static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
1.4 misho 271: return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
1.2 misho 272: (double)(pEnd->tv_sec - pStart->tv_sec);
273: }
274:
275: /*
276: ** Print the timing results.
277: */
278: static void endTimer(void){
279: if( enableTimer ){
1.4 misho 280: sqlite3_int64 iEnd = timeOfDay();
1.2 misho 281: struct rusage sEnd;
282: getrusage(RUSAGE_SELF, &sEnd);
1.4 misho 283: printf("Run Time: real %.3f user %f sys %f\n",
284: (iEnd - iBegin)*0.001,
1.2 misho 285: timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
286: timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
287: }
288: }
289:
290: #define BEGIN_TIMER beginTimer()
291: #define END_TIMER endTimer()
292: #define HAS_TIMER 1
293:
294: #elif (defined(_WIN32) || defined(WIN32))
295:
296: /* Saved resource information for the beginning of an operation */
297: static HANDLE hProcess;
298: static FILETIME ftKernelBegin;
299: static FILETIME ftUserBegin;
1.4 misho 300: static sqlite3_int64 ftWallBegin;
301: typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
302: LPFILETIME, LPFILETIME);
1.2 misho 303: static GETPROCTIMES getProcessTimesAddr = NULL;
304:
305: /*
306: ** Check to see if we have timer support. Return 1 if necessary
307: ** support found (or found previously).
308: */
309: static int hasTimer(void){
310: if( getProcessTimesAddr ){
311: return 1;
312: } else {
1.4 misho 313: /* GetProcessTimes() isn't supported in WIN95 and some other Windows
314: ** versions. See if the version we are running on has it, and if it
315: ** does, save off a pointer to it and the current process handle.
1.2 misho 316: */
317: hProcess = GetCurrentProcess();
318: if( hProcess ){
319: HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
320: if( NULL != hinstLib ){
1.4 misho 321: getProcessTimesAddr =
322: (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
1.2 misho 323: if( NULL != getProcessTimesAddr ){
324: return 1;
325: }
1.4 misho 326: FreeLibrary(hinstLib);
1.2 misho 327: }
328: }
329: }
330: return 0;
331: }
332:
333: /*
334: ** Begin timing an operation
335: */
336: static void beginTimer(void){
337: if( enableTimer && getProcessTimesAddr ){
338: FILETIME ftCreation, ftExit;
1.4 misho 339: getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
340: &ftKernelBegin,&ftUserBegin);
341: ftWallBegin = timeOfDay();
1.2 misho 342: }
343: }
344:
345: /* Return the difference of two FILETIME structs in seconds */
346: static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
347: sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
348: sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
349: return (double) ((i64End - i64Start) / 10000000.0);
350: }
351:
352: /*
353: ** Print the timing results.
354: */
355: static void endTimer(void){
356: if( enableTimer && getProcessTimesAddr){
357: FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
1.4 misho 358: sqlite3_int64 ftWallEnd = timeOfDay();
359: getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
360: printf("Run Time: real %.3f user %f sys %f\n",
361: (ftWallEnd - ftWallBegin)*0.001,
1.2 misho 362: timeDiff(&ftUserBegin, &ftUserEnd),
363: timeDiff(&ftKernelBegin, &ftKernelEnd));
364: }
365: }
366:
367: #define BEGIN_TIMER beginTimer()
368: #define END_TIMER endTimer()
369: #define HAS_TIMER hasTimer()
370:
371: #else
1.4 misho 372: #define BEGIN_TIMER
1.2 misho 373: #define END_TIMER
374: #define HAS_TIMER 0
375: #endif
376:
377: /*
378: ** Used to prevent warnings about unused parameters
379: */
380: #define UNUSED_PARAMETER(x) (void)(x)
381:
382: /*
1.4.2.2 ! misho 383: ** Number of elements in an array
! 384: */
! 385: #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
! 386:
! 387: /*
1.2 misho 388: ** If the following flag is set, then command execution stops
389: ** at an error if we are not interactive.
390: */
391: static int bail_on_error = 0;
392:
393: /*
394: ** Threat stdin as an interactive input if the following variable
395: ** is true. Otherwise, assume stdin is connected to a file or pipe.
396: */
397: static int stdin_is_interactive = 1;
398:
399: /*
1.4 misho 400: ** On Windows systems we have to know if standard output is a console
401: ** in order to translate UTF-8 into MBCS. The following variable is
402: ** true if translation is required.
403: */
404: static int stdout_is_console = 1;
405:
406: /*
1.2 misho 407: ** The following is the open SQLite database. We make a pointer
408: ** to this database a static variable so that it can be accessed
409: ** by the SIGINT handler to interrupt database processing.
410: */
1.4 misho 411: static sqlite3 *globalDb = 0;
1.2 misho 412:
413: /*
414: ** True if an interrupt (Control-C) has been received.
415: */
416: static volatile int seenInterrupt = 0;
417:
418: /*
419: ** This is the name of our program. It is set in main(), used
420: ** in a number of other places, mostly for error messages.
421: */
422: static char *Argv0;
423:
424: /*
425: ** Prompt strings. Initialized in main. Settable with
426: ** .prompt main continue
427: */
428: static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
429: static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
430:
431: /*
1.4 misho 432: ** Render output like fprintf(). Except, if the output is going to the
433: ** console and if this is running on a Windows machine, translate the
434: ** output from UTF-8 into MBCS.
435: */
436: #if defined(_WIN32) || defined(WIN32)
437: void utf8_printf(FILE *out, const char *zFormat, ...){
438: va_list ap;
439: va_start(ap, zFormat);
440: if( stdout_is_console && (out==stdout || out==stderr) ){
441: char *z1 = sqlite3_vmprintf(zFormat, ap);
442: char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
443: sqlite3_free(z1);
444: fputs(z2, out);
445: sqlite3_free(z2);
446: }else{
447: vfprintf(out, zFormat, ap);
448: }
449: va_end(ap);
450: }
451: #elif !defined(utf8_printf)
452: # define utf8_printf fprintf
453: #endif
454:
455: /*
456: ** Render output like fprintf(). This should not be used on anything that
457: ** includes string formatting (e.g. "%s").
458: */
459: #if !defined(raw_printf)
460: # define raw_printf fprintf
461: #endif
462:
1.4.2.2 ! misho 463: /* Indicate out-of-memory and exit. */
! 464: static void shell_out_of_memory(void){
! 465: raw_printf(stderr,"Error: out of memory\n");
! 466: exit(1);
! 467: }
! 468:
1.4 misho 469: /*
1.2 misho 470: ** Write I/O traces to the following stream.
471: */
472: #ifdef SQLITE_ENABLE_IOTRACE
473: static FILE *iotrace = 0;
474: #endif
475:
476: /*
477: ** This routine works like printf in that its first argument is a
478: ** format string and subsequent arguments are values to be substituted
479: ** in place of % fields. The result of formatting this string
480: ** is written to iotrace.
481: */
482: #ifdef SQLITE_ENABLE_IOTRACE
1.4 misho 483: static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
1.2 misho 484: va_list ap;
485: char *z;
486: if( iotrace==0 ) return;
487: va_start(ap, zFormat);
488: z = sqlite3_vmprintf(zFormat, ap);
489: va_end(ap);
1.4 misho 490: utf8_printf(iotrace, "%s", z);
1.2 misho 491: sqlite3_free(z);
492: }
493: #endif
494:
1.4.2.1 misho 495: /*
496: ** Output string zUtf to stream pOut as w characters. If w is negative,
497: ** then right-justify the text. W is the width in UTF-8 characters, not
498: ** in bytes. This is different from the %*.*s specification in printf
499: ** since with %*.*s the width is measured in bytes, not characters.
500: */
501: static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
502: int i;
503: int n;
504: int aw = w<0 ? -w : w;
505: char zBuf[1000];
506: if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
507: for(i=n=0; zUtf[i]; i++){
508: if( (zUtf[i]&0xc0)!=0x80 ){
509: n++;
510: if( n==aw ){
511: do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
512: break;
513: }
514: }
515: }
516: if( n>=aw ){
517: utf8_printf(pOut, "%.*s", i, zUtf);
518: }else if( w<0 ){
519: utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
520: }else{
521: utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
522: }
523: }
524:
1.2 misho 525:
526: /*
527: ** Determines if a string is a number of not.
528: */
529: static int isNumber(const char *z, int *realnum){
530: if( *z=='-' || *z=='+' ) z++;
531: if( !IsDigit(*z) ){
532: return 0;
533: }
534: z++;
535: if( realnum ) *realnum = 0;
536: while( IsDigit(*z) ){ z++; }
537: if( *z=='.' ){
538: z++;
539: if( !IsDigit(*z) ) return 0;
540: while( IsDigit(*z) ){ z++; }
541: if( realnum ) *realnum = 1;
542: }
543: if( *z=='e' || *z=='E' ){
544: z++;
545: if( *z=='+' || *z=='-' ) z++;
546: if( !IsDigit(*z) ) return 0;
547: while( IsDigit(*z) ){ z++; }
548: if( realnum ) *realnum = 1;
549: }
550: return *z==0;
551: }
552:
553: /*
1.4 misho 554: ** Compute a string length that is limited to what can be stored in
555: ** lower 30 bits of a 32-bit signed integer.
556: */
557: static int strlen30(const char *z){
558: const char *z2 = z;
559: while( *z2 ){ z2++; }
560: return 0x3fffffff & (int)(z2 - z);
561: }
562:
563: /*
1.4.2.2 ! misho 564: ** Return the length of a string in characters. Multibyte UTF8 characters
! 565: ** count as a single character.
! 566: */
! 567: static int strlenChar(const char *z){
! 568: int n = 0;
! 569: while( *z ){
! 570: if( (0xc0&*(z++))!=0x80 ) n++;
! 571: }
! 572: return n;
! 573: }
! 574:
! 575: /*
1.2 misho 576: ** This routine reads a line of text from FILE in, stores
577: ** the text in memory obtained from malloc() and returns a pointer
578: ** to the text. NULL is returned at end of file, or if malloc()
579: ** fails.
580: **
1.4 misho 581: ** If zLine is not NULL then it is a malloced buffer returned from
582: ** a previous call to this routine that may be reused.
1.2 misho 583: */
1.4 misho 584: static char *local_getline(char *zLine, FILE *in){
585: int nLine = zLine==0 ? 0 : 100;
586: int n = 0;
1.2 misho 587:
588: while( 1 ){
589: if( n+100>nLine ){
590: nLine = nLine*2 + 100;
591: zLine = realloc(zLine, nLine);
1.4.2.2 ! misho 592: if( zLine==0 ) shell_out_of_memory();
1.2 misho 593: }
594: if( fgets(&zLine[n], nLine - n, in)==0 ){
595: if( n==0 ){
596: free(zLine);
597: return 0;
598: }
599: zLine[n] = 0;
600: break;
601: }
1.4 misho 602: while( zLine[n] ) n++;
603: if( n>0 && zLine[n-1]=='\n' ){
1.2 misho 604: n--;
605: if( n>0 && zLine[n-1]=='\r' ) n--;
606: zLine[n] = 0;
607: break;
608: }
609: }
1.4 misho 610: #if defined(_WIN32) || defined(WIN32)
611: /* For interactive input on Windows systems, translate the
612: ** multi-byte characterset characters into UTF-8. */
613: if( stdin_is_interactive && in==stdin ){
614: char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
615: if( zTrans ){
616: int nTrans = strlen30(zTrans)+1;
617: if( nTrans>nLine ){
618: zLine = realloc(zLine, nTrans);
1.4.2.2 ! misho 619: if( zLine==0 ) shell_out_of_memory();
1.4 misho 620: }
621: memcpy(zLine, zTrans, nTrans);
622: sqlite3_free(zTrans);
623: }
624: }
625: #endif /* defined(_WIN32) || defined(WIN32) */
1.2 misho 626: return zLine;
627: }
628:
629: /*
630: ** Retrieve a single line of input text.
631: **
1.4 misho 632: ** If in==0 then read from standard input and prompt before each line.
633: ** If isContinuation is true, then a continuation prompt is appropriate.
634: ** If isContinuation is zero, then the main prompt should be used.
635: **
636: ** If zPrior is not NULL then it is a buffer from a prior call to this
637: ** routine that can be reused.
638: **
639: ** The result is stored in space obtained from malloc() and must either
640: ** be freed by the caller or else passed back into this routine via the
641: ** zPrior argument for reuse.
1.2 misho 642: */
1.4 misho 643: static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
1.2 misho 644: char *zPrompt;
645: char *zResult;
646: if( in!=0 ){
1.4 misho 647: zResult = local_getline(zPrior, in);
1.2 misho 648: }else{
1.4 misho 649: zPrompt = isContinuation ? continuePrompt : mainPrompt;
650: #if SHELL_USE_LOCAL_GETLINE
651: printf("%s", zPrompt);
652: fflush(stdout);
653: zResult = local_getline(zPrior, stdin);
654: #else
655: free(zPrior);
656: zResult = shell_readline(zPrompt);
657: if( zResult && *zResult ) shell_add_history(zResult);
658: #endif
1.2 misho 659: }
660: return zResult;
661: }
1.4.2.2 ! misho 662:
! 663:
! 664: /*
! 665: ** Return the value of a hexadecimal digit. Return -1 if the input
! 666: ** is not a hex digit.
! 667: */
! 668: static int hexDigitValue(char c){
! 669: if( c>='0' && c<='9' ) return c - '0';
! 670: if( c>='a' && c<='f' ) return c - 'a' + 10;
! 671: if( c>='A' && c<='F' ) return c - 'A' + 10;
! 672: return -1;
! 673: }
! 674:
! 675: /*
! 676: ** Interpret zArg as an integer value, possibly with suffixes.
! 677: */
! 678: static sqlite3_int64 integerValue(const char *zArg){
! 679: sqlite3_int64 v = 0;
! 680: static const struct { char *zSuffix; int iMult; } aMult[] = {
! 681: { "KiB", 1024 },
! 682: { "MiB", 1024*1024 },
! 683: { "GiB", 1024*1024*1024 },
! 684: { "KB", 1000 },
! 685: { "MB", 1000000 },
! 686: { "GB", 1000000000 },
! 687: { "K", 1000 },
! 688: { "M", 1000000 },
! 689: { "G", 1000000000 },
! 690: };
! 691: int i;
! 692: int isNeg = 0;
! 693: if( zArg[0]=='-' ){
! 694: isNeg = 1;
! 695: zArg++;
! 696: }else if( zArg[0]=='+' ){
! 697: zArg++;
! 698: }
! 699: if( zArg[0]=='0' && zArg[1]=='x' ){
! 700: int x;
! 701: zArg += 2;
! 702: while( (x = hexDigitValue(zArg[0]))>=0 ){
! 703: v = (v<<4) + x;
! 704: zArg++;
! 705: }
! 706: }else{
! 707: while( IsDigit(zArg[0]) ){
! 708: v = v*10 + zArg[0] - '0';
! 709: zArg++;
! 710: }
! 711: }
! 712: for(i=0; i<ArraySize(aMult); i++){
! 713: if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
! 714: v *= aMult[i].iMult;
! 715: break;
! 716: }
! 717: }
! 718: return isNeg? -v : v;
! 719: }
! 720:
1.4.2.1 misho 721: /*
722: ** A variable length string to which one can append text.
723: */
724: typedef struct ShellText ShellText;
725: struct ShellText {
726: char *z;
727: int n;
728: int nAlloc;
729: };
730:
731: /*
732: ** Initialize and destroy a ShellText object
733: */
734: static void initText(ShellText *p){
735: memset(p, 0, sizeof(*p));
736: }
737: static void freeText(ShellText *p){
738: free(p->z);
739: initText(p);
740: }
741:
742: /* zIn is either a pointer to a NULL-terminated string in memory obtained
743: ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
744: ** added to zIn, and the result returned in memory obtained from malloc().
745: ** zIn, if it was not NULL, is freed.
746: **
747: ** If the third argument, quote, is not '\0', then it is used as a
748: ** quote character for zAppend.
749: */
750: static void appendText(ShellText *p, char const *zAppend, char quote){
751: int len;
752: int i;
753: int nAppend = strlen30(zAppend);
754:
755: len = nAppend+p->n+1;
756: if( quote ){
757: len += 2;
758: for(i=0; i<nAppend; i++){
759: if( zAppend[i]==quote ) len++;
760: }
761: }
762:
763: if( p->n+len>=p->nAlloc ){
764: p->nAlloc = p->nAlloc*2 + len + 20;
765: p->z = realloc(p->z, p->nAlloc);
1.4.2.2 ! misho 766: if( p->z==0 ) shell_out_of_memory();
1.4.2.1 misho 767: }
768:
769: if( quote ){
770: char *zCsr = p->z+p->n;
771: *zCsr++ = quote;
772: for(i=0; i<nAppend; i++){
773: *zCsr++ = zAppend[i];
774: if( zAppend[i]==quote ) *zCsr++ = quote;
775: }
776: *zCsr++ = quote;
777: p->n = (int)(zCsr - p->z);
778: *zCsr = '\0';
779: }else{
780: memcpy(p->z+p->n, zAppend, nAppend);
781: p->n += nAppend;
782: p->z[p->n] = '\0';
783: }
784: }
785:
786: /*
787: ** Attempt to determine if identifier zName needs to be quoted, either
788: ** because it contains non-alphanumeric characters, or because it is an
789: ** SQLite keyword. Be conservative in this estimate: When in doubt assume
790: ** that quoting is required.
791: **
792: ** Return '"' if quoting is required. Return 0 if no quoting is required.
793: */
794: static char quoteChar(const char *zName){
1.4.2.2 ! misho 795: int i;
1.4.2.1 misho 796: if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
797: for(i=0; zName[i]; i++){
798: if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
799: }
1.4.2.2 ! misho 800: return sqlite3_keyword_check(zName, i) ? '"' : 0;
! 801: }
! 802:
! 803: /*
! 804: ** Construct a fake object name and column list to describe the structure
! 805: ** of the view, virtual table, or table valued function zSchema.zName.
! 806: */
! 807: static char *shellFakeSchema(
! 808: sqlite3 *db, /* The database connection containing the vtab */
! 809: const char *zSchema, /* Schema of the database holding the vtab */
! 810: const char *zName /* The name of the virtual table */
! 811: ){
! 812: sqlite3_stmt *pStmt = 0;
! 813: char *zSql;
! 814: ShellText s;
! 815: char cQuote;
! 816: char *zDiv = "(";
! 817: int nRow = 0;
! 818:
! 819: zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
! 820: zSchema ? zSchema : "main", zName);
! 821: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
! 822: sqlite3_free(zSql);
! 823: initText(&s);
! 824: if( zSchema ){
! 825: cQuote = quoteChar(zSchema);
! 826: if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
! 827: appendText(&s, zSchema, cQuote);
! 828: appendText(&s, ".", 0);
! 829: }
! 830: cQuote = quoteChar(zName);
! 831: appendText(&s, zName, cQuote);
! 832: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 833: const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
! 834: nRow++;
! 835: appendText(&s, zDiv, 0);
! 836: zDiv = ",";
! 837: cQuote = quoteChar(zCol);
! 838: appendText(&s, zCol, cQuote);
! 839: }
! 840: appendText(&s, ")", 0);
! 841: sqlite3_finalize(pStmt);
! 842: if( nRow==0 ){
! 843: freeText(&s);
! 844: s.z = 0;
! 845: }
! 846: return s.z;
! 847: }
! 848:
! 849: /*
! 850: ** SQL function: shell_module_schema(X)
! 851: **
! 852: ** Return a fake schema for the table-valued function or eponymous virtual
! 853: ** table X.
! 854: */
! 855: static void shellModuleSchema(
! 856: sqlite3_context *pCtx,
! 857: int nVal,
! 858: sqlite3_value **apVal
! 859: ){
! 860: const char *zName = (const char*)sqlite3_value_text(apVal[0]);
! 861: char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
! 862: UNUSED_PARAMETER(nVal);
! 863: if( zFake ){
! 864: sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
! 865: -1, sqlite3_free);
! 866: free(zFake);
! 867: }
! 868: }
! 869:
! 870: /*
! 871: ** SQL function: shell_add_schema(S,X)
! 872: **
! 873: ** Add the schema name X to the CREATE statement in S and return the result.
! 874: ** Examples:
! 875: **
! 876: ** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
! 877: **
! 878: ** Also works on
! 879: **
! 880: ** CREATE INDEX
! 881: ** CREATE UNIQUE INDEX
! 882: ** CREATE VIEW
! 883: ** CREATE TRIGGER
! 884: ** CREATE VIRTUAL TABLE
! 885: **
! 886: ** This UDF is used by the .schema command to insert the schema name of
! 887: ** attached databases into the middle of the sqlite_master.sql field.
! 888: */
! 889: static void shellAddSchemaName(
! 890: sqlite3_context *pCtx,
! 891: int nVal,
! 892: sqlite3_value **apVal
! 893: ){
! 894: static const char *aPrefix[] = {
! 895: "TABLE",
! 896: "INDEX",
! 897: "UNIQUE INDEX",
! 898: "VIEW",
! 899: "TRIGGER",
! 900: "VIRTUAL TABLE"
! 901: };
! 902: int i = 0;
! 903: const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
! 904: const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
! 905: const char *zName = (const char*)sqlite3_value_text(apVal[2]);
! 906: sqlite3 *db = sqlite3_context_db_handle(pCtx);
! 907: UNUSED_PARAMETER(nVal);
! 908: if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
! 909: for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
! 910: int n = strlen30(aPrefix[i]);
! 911: if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
! 912: char *z = 0;
! 913: char *zFake = 0;
! 914: if( zSchema ){
! 915: char cQuote = quoteChar(zSchema);
! 916: if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
! 917: z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
! 918: }else{
! 919: z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
! 920: }
! 921: }
! 922: if( zName
! 923: && aPrefix[i][0]=='V'
! 924: && (zFake = shellFakeSchema(db, zSchema, zName))!=0
! 925: ){
! 926: if( z==0 ){
! 927: z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
! 928: }else{
! 929: z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
! 930: }
! 931: free(zFake);
! 932: }
! 933: if( z ){
! 934: sqlite3_result_text(pCtx, z, -1, sqlite3_free);
! 935: return;
! 936: }
! 937: }
1.4.2.1 misho 938: }
939: }
1.4.2.2 ! misho 940: sqlite3_result_value(pCtx, apVal[0]);
1.4.2.1 misho 941: }
942:
1.4.2.2 ! misho 943: /*
! 944: ** The source code for several run-time loadable extensions is inserted
! 945: ** below by the ../tool/mkshellc.tcl script. Before processing that included
! 946: ** code, we need to override some macros to make the included program code
! 947: ** work here in the middle of this regular program.
1.4.2.1 misho 948: */
1.4.2.2 ! misho 949: #define SQLITE_EXTENSION_INIT1
! 950: #define SQLITE_EXTENSION_INIT2(X) (void)(X)
! 951:
! 952: #if defined(_WIN32) && defined(_MSC_VER)
! 953: /************************* Begin test_windirent.h ******************/
1.4.2.1 misho 954: /*
1.4.2.2 ! misho 955: ** 2015 November 30
1.4.2.1 misho 956: **
1.4.2.2 ! misho 957: ** The author disclaims copyright to this source code. In place of
! 958: ** a legal notice, here is a blessing:
! 959: **
! 960: ** May you do good and not evil.
! 961: ** May you find forgiveness for yourself and forgive others.
! 962: ** May you share freely, never taking more than you give.
! 963: **
! 964: *************************************************************************
! 965: ** This file contains declarations for most of the opendir() family of
! 966: ** POSIX functions on Win32 using the MSVCRT.
1.4.2.1 misho 967: */
1.4.2.2 ! misho 968:
! 969: #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
! 970: #define SQLITE_WINDIRENT_H
! 971:
! 972: /*
! 973: ** We need several data types from the Windows SDK header.
! 974: */
! 975:
! 976: #ifndef WIN32_LEAN_AND_MEAN
! 977: #define WIN32_LEAN_AND_MEAN
1.4.2.1 misho 978: #endif
979:
1.4.2.2 ! misho 980: #include "windows.h"
1.4.2.1 misho 981:
982: /*
1.4.2.2 ! misho 983: ** We need several support functions from the SQLite core.
1.4.2.1 misho 984: */
985:
1.4.2.2 ! misho 986: /* #include "sqlite3.h" */
1.4.2.1 misho 987:
988: /*
1.4.2.2 ! misho 989: ** We need several things from the ANSI and MSVCRT headers.
1.4.2.1 misho 990: */
991:
1.4.2.2 ! misho 992: #include <stdio.h>
! 993: #include <stdlib.h>
! 994: #include <errno.h>
! 995: #include <io.h>
! 996: #include <limits.h>
! 997: #include <sys/types.h>
! 998: #include <sys/stat.h>
1.4.2.1 misho 999:
1000: /*
1.4.2.2 ! misho 1001: ** We may need several defines that should have been in "sys/stat.h".
1.4.2.1 misho 1002: */
1.4.2.2 ! misho 1003:
! 1004: #ifndef S_ISREG
! 1005: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
! 1006: #endif
! 1007:
! 1008: #ifndef S_ISDIR
! 1009: #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
! 1010: #endif
! 1011:
! 1012: #ifndef S_ISLNK
! 1013: #define S_ISLNK(mode) (0)
1.4.2.1 misho 1014: #endif
1015:
1016: /*
1.4.2.2 ! misho 1017: ** We may need to provide the "mode_t" type.
1.4.2.1 misho 1018: */
1.4.2.2 ! misho 1019:
! 1020: #ifndef MODE_T_DEFINED
! 1021: #define MODE_T_DEFINED
! 1022: typedef unsigned short mode_t;
1.4.2.1 misho 1023: #endif
1.4.2.2 ! misho 1024:
! 1025: /*
! 1026: ** We may need to provide the "ino_t" type.
! 1027: */
! 1028:
! 1029: #ifndef INO_T_DEFINED
! 1030: #define INO_T_DEFINED
! 1031: typedef unsigned short ino_t;
1.4.2.1 misho 1032: #endif
1.4.2.2 ! misho 1033:
! 1034: /*
! 1035: ** We need to define "NAME_MAX" if it was not present in "limits.h".
! 1036: */
! 1037:
! 1038: #ifndef NAME_MAX
! 1039: # ifdef FILENAME_MAX
! 1040: # define NAME_MAX (FILENAME_MAX)
! 1041: # else
! 1042: # define NAME_MAX (260)
! 1043: # endif
! 1044: #endif
! 1045:
! 1046: /*
! 1047: ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
! 1048: */
! 1049:
! 1050: #ifndef NULL_INTPTR_T
! 1051: # define NULL_INTPTR_T ((intptr_t)(0))
! 1052: #endif
! 1053:
! 1054: #ifndef BAD_INTPTR_T
! 1055: # define BAD_INTPTR_T ((intptr_t)(-1))
! 1056: #endif
! 1057:
! 1058: /*
! 1059: ** We need to provide the necessary structures and related types.
! 1060: */
! 1061:
! 1062: #ifndef DIRENT_DEFINED
! 1063: #define DIRENT_DEFINED
! 1064: typedef struct DIRENT DIRENT;
! 1065: typedef DIRENT *LPDIRENT;
! 1066: struct DIRENT {
! 1067: ino_t d_ino; /* Sequence number, do not use. */
! 1068: unsigned d_attributes; /* Win32 file attributes. */
! 1069: char d_name[NAME_MAX + 1]; /* Name within the directory. */
! 1070: };
! 1071: #endif
! 1072:
! 1073: #ifndef DIR_DEFINED
! 1074: #define DIR_DEFINED
! 1075: typedef struct DIR DIR;
! 1076: typedef DIR *LPDIR;
! 1077: struct DIR {
! 1078: intptr_t d_handle; /* Value returned by "_findfirst". */
! 1079: DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
! 1080: DIRENT d_next; /* DIRENT constructed based on "_findnext". */
! 1081: };
! 1082: #endif
! 1083:
! 1084: /*
! 1085: ** Provide a macro, for use by the implementation, to determine if a
! 1086: ** particular directory entry should be skipped over when searching for
! 1087: ** the next directory entry that should be returned by the readdir() or
! 1088: ** readdir_r() functions.
! 1089: */
! 1090:
! 1091: #ifndef is_filtered
! 1092: # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
! 1093: #endif
! 1094:
! 1095: /*
! 1096: ** Provide the function prototype for the POSIX compatiable getenv()
! 1097: ** function. This function is not thread-safe.
! 1098: */
! 1099:
! 1100: extern const char *windirent_getenv(const char *name);
! 1101:
! 1102: /*
! 1103: ** Finally, we can provide the function prototypes for the opendir(),
! 1104: ** readdir(), readdir_r(), and closedir() POSIX functions.
! 1105: */
! 1106:
! 1107: extern LPDIR opendir(const char *dirname);
! 1108: extern LPDIRENT readdir(LPDIR dirp);
! 1109: extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
! 1110: extern INT closedir(LPDIR dirp);
! 1111:
! 1112: #endif /* defined(WIN32) && defined(_MSC_VER) */
! 1113:
! 1114: /************************* End test_windirent.h ********************/
! 1115: /************************* Begin test_windirent.c ******************/
! 1116: /*
! 1117: ** 2015 November 30
! 1118: **
! 1119: ** The author disclaims copyright to this source code. In place of
! 1120: ** a legal notice, here is a blessing:
! 1121: **
! 1122: ** May you do good and not evil.
! 1123: ** May you find forgiveness for yourself and forgive others.
! 1124: ** May you share freely, never taking more than you give.
! 1125: **
! 1126: *************************************************************************
! 1127: ** This file contains code to implement most of the opendir() family of
! 1128: ** POSIX functions on Win32 using the MSVCRT.
! 1129: */
! 1130:
! 1131: #if defined(_WIN32) && defined(_MSC_VER)
! 1132: /* #include "test_windirent.h" */
! 1133:
! 1134: /*
! 1135: ** Implementation of the POSIX getenv() function using the Win32 API.
! 1136: ** This function is not thread-safe.
! 1137: */
! 1138: const char *windirent_getenv(
! 1139: const char *name
! 1140: ){
! 1141: static char value[32768]; /* Maximum length, per MSDN */
! 1142: DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
! 1143: DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
! 1144:
! 1145: memset(value, 0, sizeof(value));
! 1146: dwRet = GetEnvironmentVariableA(name, value, dwSize);
! 1147: if( dwRet==0 || dwRet>dwSize ){
! 1148: /*
! 1149: ** The function call to GetEnvironmentVariableA() failed -OR-
! 1150: ** the buffer is not large enough. Either way, return NULL.
! 1151: */
! 1152: return 0;
! 1153: }else{
! 1154: /*
! 1155: ** The function call to GetEnvironmentVariableA() succeeded
! 1156: ** -AND- the buffer contains the entire value.
! 1157: */
! 1158: return value;
1.4.2.1 misho 1159: }
1160: }
1161:
1162: /*
1.4.2.2 ! misho 1163: ** Implementation of the POSIX opendir() function using the MSVCRT.
1.4.2.1 misho 1164: */
1.4.2.2 ! misho 1165: LPDIR opendir(
! 1166: const char *dirname
! 1167: ){
! 1168: struct _finddata_t data;
! 1169: LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
! 1170: SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
! 1171:
! 1172: if( dirp==NULL ) return NULL;
! 1173: memset(dirp, 0, sizeof(DIR));
! 1174:
! 1175: /* TODO: Remove this if Unix-style root paths are not used. */
! 1176: if( sqlite3_stricmp(dirname, "/")==0 ){
! 1177: dirname = windirent_getenv("SystemDrive");
1.4.2.1 misho 1178: }
1.4.2.2 ! misho 1179:
! 1180: memset(&data, 0, sizeof(struct _finddata_t));
! 1181: _snprintf(data.name, namesize, "%s\\*", dirname);
! 1182: dirp->d_handle = _findfirst(data.name, &data);
! 1183:
! 1184: if( dirp->d_handle==BAD_INTPTR_T ){
! 1185: closedir(dirp);
! 1186: return NULL;
1.4.2.1 misho 1187: }
1.4.2.2 ! misho 1188:
! 1189: /* TODO: Remove this block to allow hidden and/or system files. */
! 1190: if( is_filtered(data) ){
! 1191: next:
! 1192:
! 1193: memset(&data, 0, sizeof(struct _finddata_t));
! 1194: if( _findnext(dirp->d_handle, &data)==-1 ){
! 1195: closedir(dirp);
! 1196: return NULL;
! 1197: }
! 1198:
! 1199: /* TODO: Remove this block to allow hidden and/or system files. */
! 1200: if( is_filtered(data) ) goto next;
! 1201: }
! 1202:
! 1203: dirp->d_first.d_attributes = data.attrib;
! 1204: strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
! 1205: dirp->d_first.d_name[NAME_MAX] = '\0';
! 1206:
! 1207: return dirp;
1.4.2.1 misho 1208: }
1209:
1210: /*
1.4.2.2 ! misho 1211: ** Implementation of the POSIX readdir() function using the MSVCRT.
1.4.2.1 misho 1212: */
1.4.2.2 ! misho 1213: LPDIRENT readdir(
! 1214: LPDIR dirp
1.4.2.1 misho 1215: ){
1.4.2.2 ! misho 1216: struct _finddata_t data;
! 1217:
! 1218: if( dirp==NULL ) return NULL;
! 1219:
! 1220: if( dirp->d_first.d_ino==0 ){
! 1221: dirp->d_first.d_ino++;
! 1222: dirp->d_next.d_ino++;
! 1223:
! 1224: return &dirp->d_first;
1.4.2.1 misho 1225: }
1.4.2.2 ! misho 1226:
! 1227: next:
! 1228:
! 1229: memset(&data, 0, sizeof(struct _finddata_t));
! 1230: if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
! 1231:
! 1232: /* TODO: Remove this block to allow hidden and/or system files. */
! 1233: if( is_filtered(data) ) goto next;
! 1234:
! 1235: dirp->d_next.d_ino++;
! 1236: dirp->d_next.d_attributes = data.attrib;
! 1237: strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
! 1238: dirp->d_next.d_name[NAME_MAX] = '\0';
! 1239:
! 1240: return &dirp->d_next;
! 1241: }
! 1242:
! 1243: /*
! 1244: ** Implementation of the POSIX readdir_r() function using the MSVCRT.
! 1245: */
! 1246: INT readdir_r(
! 1247: LPDIR dirp,
! 1248: LPDIRENT entry,
! 1249: LPDIRENT *result
! 1250: ){
! 1251: struct _finddata_t data;
! 1252:
! 1253: if( dirp==NULL ) return EBADF;
! 1254:
! 1255: if( dirp->d_first.d_ino==0 ){
! 1256: dirp->d_first.d_ino++;
! 1257: dirp->d_next.d_ino++;
! 1258:
! 1259: entry->d_ino = dirp->d_first.d_ino;
! 1260: entry->d_attributes = dirp->d_first.d_attributes;
! 1261: strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
! 1262: entry->d_name[NAME_MAX] = '\0';
! 1263:
! 1264: *result = entry;
! 1265: return 0;
1.4.2.1 misho 1266: }
1.4.2.2 ! misho 1267:
! 1268: next:
! 1269:
! 1270: memset(&data, 0, sizeof(struct _finddata_t));
! 1271: if( _findnext(dirp->d_handle, &data)==-1 ){
! 1272: *result = NULL;
! 1273: return ENOENT;
! 1274: }
! 1275:
! 1276: /* TODO: Remove this block to allow hidden and/or system files. */
! 1277: if( is_filtered(data) ) goto next;
! 1278:
! 1279: entry->d_ino = (ino_t)-1; /* not available */
! 1280: entry->d_attributes = data.attrib;
! 1281: strncpy(entry->d_name, data.name, NAME_MAX);
! 1282: entry->d_name[NAME_MAX] = '\0';
! 1283:
! 1284: *result = entry;
! 1285: return 0;
1.4.2.1 misho 1286: }
1287:
1.4.2.2 ! misho 1288: /*
! 1289: ** Implementation of the POSIX closedir() function using the MSVCRT.
1.4.2.1 misho 1290: */
1.4.2.2 ! misho 1291: INT closedir(
! 1292: LPDIR dirp
1.4.2.1 misho 1293: ){
1.4.2.2 ! misho 1294: INT result = 0;
! 1295:
! 1296: if( dirp==NULL ) return EINVAL;
! 1297:
! 1298: if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
! 1299: result = _findclose(dirp->d_handle);
! 1300: }
! 1301:
! 1302: sqlite3_free(dirp);
! 1303: return result;
1.4.2.1 misho 1304: }
1305:
1.4.2.2 ! misho 1306: #endif /* defined(WIN32) && defined(_MSC_VER) */
! 1307:
! 1308: /************************* End test_windirent.c ********************/
! 1309: #define dirent DIRENT
! 1310: #endif
! 1311: /************************* Begin ../ext/misc/shathree.c ******************/
1.4.2.1 misho 1312: /*
1.4.2.2 ! misho 1313: ** 2017-03-08
1.4.2.1 misho 1314: **
1.4.2.2 ! misho 1315: ** The author disclaims copyright to this source code. In place of
! 1316: ** a legal notice, here is a blessing:
1.4.2.1 misho 1317: **
1.4.2.2 ! misho 1318: ** May you do good and not evil.
! 1319: ** May you find forgiveness for yourself and forgive others.
! 1320: ** May you share freely, never taking more than you give.
1.4.2.1 misho 1321: **
1.4.2.2 ! misho 1322: ******************************************************************************
1.4.2.1 misho 1323: **
1.4.2.2 ! misho 1324: ** This SQLite extension implements functions that compute SHA3 hashes.
! 1325: ** Two SQL functions are implemented:
1.4.2.1 misho 1326: **
1.4.2.2 ! misho 1327: ** sha3(X,SIZE)
! 1328: ** sha3_query(Y,SIZE)
! 1329: **
! 1330: ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
! 1331: ** X is NULL.
! 1332: **
! 1333: ** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
! 1334: ** and returns a hash of their results.
! 1335: **
! 1336: ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
! 1337: ** is used. If SIZE is included it must be one of the integers 224, 256,
! 1338: ** 384, or 512, to determine SHA3 hash variant that is computed.
1.4.2.1 misho 1339: */
1.4.2.2 ! misho 1340: /* #include "sqlite3ext.h" */
! 1341: SQLITE_EXTENSION_INIT1
! 1342: #include <assert.h>
! 1343: #include <string.h>
! 1344: #include <stdarg.h>
! 1345: /* typedef sqlite3_uint64 u64; */
1.4.2.1 misho 1346:
1.4.2.2 ! misho 1347: /******************************************************************************
! 1348: ** The Hash Engine
! 1349: */
1.4 misho 1350: /*
1.4.2.2 ! misho 1351: ** Macros to determine whether the machine is big or little endian,
! 1352: ** and whether or not that determination is run-time or compile-time.
! 1353: **
! 1354: ** For best performance, an attempt is made to guess at the byte-order
! 1355: ** using C-preprocessor macros. If that is unsuccessful, or if
! 1356: ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
! 1357: ** at run-time.
1.4 misho 1358: */
1.4.2.2 ! misho 1359: #ifndef SHA3_BYTEORDER
! 1360: # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
! 1361: defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
! 1362: defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
! 1363: defined(__arm__)
! 1364: # define SHA3_BYTEORDER 1234
! 1365: # elif defined(sparc) || defined(__ppc__)
! 1366: # define SHA3_BYTEORDER 4321
! 1367: # else
! 1368: # define SHA3_BYTEORDER 0
! 1369: # endif
1.4 misho 1370: #endif
1371:
1.4.2.2 ! misho 1372:
1.4 misho 1373: /*
1.4.2.2 ! misho 1374: ** State structure for a SHA3 hash in progress
1.4 misho 1375: */
1.4.2.2 ! misho 1376: typedef struct SHA3Context SHA3Context;
! 1377: struct SHA3Context {
! 1378: union {
! 1379: u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
! 1380: unsigned char x[1600]; /* ... or 1600 bytes */
! 1381: } u;
! 1382: unsigned nRate; /* Bytes of input accepted per Keccak iteration */
! 1383: unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
! 1384: unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
1.2 misho 1385: };
1386:
1387: /*
1.4.2.2 ! misho 1388: ** A single step of the Keccak mixing function for a 1600-bit state
1.2 misho 1389: */
1.4.2.2 ! misho 1390: static void KeccakF1600Step(SHA3Context *p){
! 1391: int i;
! 1392: u64 b0, b1, b2, b3, b4;
! 1393: u64 c0, c1, c2, c3, c4;
! 1394: u64 d0, d1, d2, d3, d4;
! 1395: static const u64 RC[] = {
! 1396: 0x0000000000000001ULL, 0x0000000000008082ULL,
! 1397: 0x800000000000808aULL, 0x8000000080008000ULL,
! 1398: 0x000000000000808bULL, 0x0000000080000001ULL,
! 1399: 0x8000000080008081ULL, 0x8000000000008009ULL,
! 1400: 0x000000000000008aULL, 0x0000000000000088ULL,
! 1401: 0x0000000080008009ULL, 0x000000008000000aULL,
! 1402: 0x000000008000808bULL, 0x800000000000008bULL,
! 1403: 0x8000000000008089ULL, 0x8000000000008003ULL,
! 1404: 0x8000000000008002ULL, 0x8000000000000080ULL,
! 1405: 0x000000000000800aULL, 0x800000008000000aULL,
! 1406: 0x8000000080008081ULL, 0x8000000000008080ULL,
! 1407: 0x0000000080000001ULL, 0x8000000080008008ULL
! 1408: };
! 1409: # define a00 (p->u.s[0])
! 1410: # define a01 (p->u.s[1])
! 1411: # define a02 (p->u.s[2])
! 1412: # define a03 (p->u.s[3])
! 1413: # define a04 (p->u.s[4])
! 1414: # define a10 (p->u.s[5])
! 1415: # define a11 (p->u.s[6])
! 1416: # define a12 (p->u.s[7])
! 1417: # define a13 (p->u.s[8])
! 1418: # define a14 (p->u.s[9])
! 1419: # define a20 (p->u.s[10])
! 1420: # define a21 (p->u.s[11])
! 1421: # define a22 (p->u.s[12])
! 1422: # define a23 (p->u.s[13])
! 1423: # define a24 (p->u.s[14])
! 1424: # define a30 (p->u.s[15])
! 1425: # define a31 (p->u.s[16])
! 1426: # define a32 (p->u.s[17])
! 1427: # define a33 (p->u.s[18])
! 1428: # define a34 (p->u.s[19])
! 1429: # define a40 (p->u.s[20])
! 1430: # define a41 (p->u.s[21])
! 1431: # define a42 (p->u.s[22])
! 1432: # define a43 (p->u.s[23])
! 1433: # define a44 (p->u.s[24])
! 1434: # define ROL64(a,x) ((a<<x)|(a>>(64-x)))
! 1435:
! 1436: for(i=0; i<24; i+=4){
! 1437: c0 = a00^a10^a20^a30^a40;
! 1438: c1 = a01^a11^a21^a31^a41;
! 1439: c2 = a02^a12^a22^a32^a42;
! 1440: c3 = a03^a13^a23^a33^a43;
! 1441: c4 = a04^a14^a24^a34^a44;
! 1442: d0 = c4^ROL64(c1, 1);
! 1443: d1 = c0^ROL64(c2, 1);
! 1444: d2 = c1^ROL64(c3, 1);
! 1445: d3 = c2^ROL64(c4, 1);
! 1446: d4 = c3^ROL64(c0, 1);
! 1447:
! 1448: b0 = (a00^d0);
! 1449: b1 = ROL64((a11^d1), 44);
! 1450: b2 = ROL64((a22^d2), 43);
! 1451: b3 = ROL64((a33^d3), 21);
! 1452: b4 = ROL64((a44^d4), 14);
! 1453: a00 = b0 ^((~b1)& b2 );
! 1454: a00 ^= RC[i];
! 1455: a11 = b1 ^((~b2)& b3 );
! 1456: a22 = b2 ^((~b3)& b4 );
! 1457: a33 = b3 ^((~b4)& b0 );
! 1458: a44 = b4 ^((~b0)& b1 );
! 1459:
! 1460: b2 = ROL64((a20^d0), 3);
! 1461: b3 = ROL64((a31^d1), 45);
! 1462: b4 = ROL64((a42^d2), 61);
! 1463: b0 = ROL64((a03^d3), 28);
! 1464: b1 = ROL64((a14^d4), 20);
! 1465: a20 = b0 ^((~b1)& b2 );
! 1466: a31 = b1 ^((~b2)& b3 );
! 1467: a42 = b2 ^((~b3)& b4 );
! 1468: a03 = b3 ^((~b4)& b0 );
! 1469: a14 = b4 ^((~b0)& b1 );
! 1470:
! 1471: b4 = ROL64((a40^d0), 18);
! 1472: b0 = ROL64((a01^d1), 1);
! 1473: b1 = ROL64((a12^d2), 6);
! 1474: b2 = ROL64((a23^d3), 25);
! 1475: b3 = ROL64((a34^d4), 8);
! 1476: a40 = b0 ^((~b1)& b2 );
! 1477: a01 = b1 ^((~b2)& b3 );
! 1478: a12 = b2 ^((~b3)& b4 );
! 1479: a23 = b3 ^((~b4)& b0 );
! 1480: a34 = b4 ^((~b0)& b1 );
! 1481:
! 1482: b1 = ROL64((a10^d0), 36);
! 1483: b2 = ROL64((a21^d1), 10);
! 1484: b3 = ROL64((a32^d2), 15);
! 1485: b4 = ROL64((a43^d3), 56);
! 1486: b0 = ROL64((a04^d4), 27);
! 1487: a10 = b0 ^((~b1)& b2 );
! 1488: a21 = b1 ^((~b2)& b3 );
! 1489: a32 = b2 ^((~b3)& b4 );
! 1490: a43 = b3 ^((~b4)& b0 );
! 1491: a04 = b4 ^((~b0)& b1 );
! 1492:
! 1493: b3 = ROL64((a30^d0), 41);
! 1494: b4 = ROL64((a41^d1), 2);
! 1495: b0 = ROL64((a02^d2), 62);
! 1496: b1 = ROL64((a13^d3), 55);
! 1497: b2 = ROL64((a24^d4), 39);
! 1498: a30 = b0 ^((~b1)& b2 );
! 1499: a41 = b1 ^((~b2)& b3 );
! 1500: a02 = b2 ^((~b3)& b4 );
! 1501: a13 = b3 ^((~b4)& b0 );
! 1502: a24 = b4 ^((~b0)& b1 );
! 1503:
! 1504: c0 = a00^a20^a40^a10^a30;
! 1505: c1 = a11^a31^a01^a21^a41;
! 1506: c2 = a22^a42^a12^a32^a02;
! 1507: c3 = a33^a03^a23^a43^a13;
! 1508: c4 = a44^a14^a34^a04^a24;
! 1509: d0 = c4^ROL64(c1, 1);
! 1510: d1 = c0^ROL64(c2, 1);
! 1511: d2 = c1^ROL64(c3, 1);
! 1512: d3 = c2^ROL64(c4, 1);
! 1513: d4 = c3^ROL64(c0, 1);
! 1514:
! 1515: b0 = (a00^d0);
! 1516: b1 = ROL64((a31^d1), 44);
! 1517: b2 = ROL64((a12^d2), 43);
! 1518: b3 = ROL64((a43^d3), 21);
! 1519: b4 = ROL64((a24^d4), 14);
! 1520: a00 = b0 ^((~b1)& b2 );
! 1521: a00 ^= RC[i+1];
! 1522: a31 = b1 ^((~b2)& b3 );
! 1523: a12 = b2 ^((~b3)& b4 );
! 1524: a43 = b3 ^((~b4)& b0 );
! 1525: a24 = b4 ^((~b0)& b1 );
! 1526:
! 1527: b2 = ROL64((a40^d0), 3);
! 1528: b3 = ROL64((a21^d1), 45);
! 1529: b4 = ROL64((a02^d2), 61);
! 1530: b0 = ROL64((a33^d3), 28);
! 1531: b1 = ROL64((a14^d4), 20);
! 1532: a40 = b0 ^((~b1)& b2 );
! 1533: a21 = b1 ^((~b2)& b3 );
! 1534: a02 = b2 ^((~b3)& b4 );
! 1535: a33 = b3 ^((~b4)& b0 );
! 1536: a14 = b4 ^((~b0)& b1 );
! 1537:
! 1538: b4 = ROL64((a30^d0), 18);
! 1539: b0 = ROL64((a11^d1), 1);
! 1540: b1 = ROL64((a42^d2), 6);
! 1541: b2 = ROL64((a23^d3), 25);
! 1542: b3 = ROL64((a04^d4), 8);
! 1543: a30 = b0 ^((~b1)& b2 );
! 1544: a11 = b1 ^((~b2)& b3 );
! 1545: a42 = b2 ^((~b3)& b4 );
! 1546: a23 = b3 ^((~b4)& b0 );
! 1547: a04 = b4 ^((~b0)& b1 );
! 1548:
! 1549: b1 = ROL64((a20^d0), 36);
! 1550: b2 = ROL64((a01^d1), 10);
! 1551: b3 = ROL64((a32^d2), 15);
! 1552: b4 = ROL64((a13^d3), 56);
! 1553: b0 = ROL64((a44^d4), 27);
! 1554: a20 = b0 ^((~b1)& b2 );
! 1555: a01 = b1 ^((~b2)& b3 );
! 1556: a32 = b2 ^((~b3)& b4 );
! 1557: a13 = b3 ^((~b4)& b0 );
! 1558: a44 = b4 ^((~b0)& b1 );
! 1559:
! 1560: b3 = ROL64((a10^d0), 41);
! 1561: b4 = ROL64((a41^d1), 2);
! 1562: b0 = ROL64((a22^d2), 62);
! 1563: b1 = ROL64((a03^d3), 55);
! 1564: b2 = ROL64((a34^d4), 39);
! 1565: a10 = b0 ^((~b1)& b2 );
! 1566: a41 = b1 ^((~b2)& b3 );
! 1567: a22 = b2 ^((~b3)& b4 );
! 1568: a03 = b3 ^((~b4)& b0 );
! 1569: a34 = b4 ^((~b0)& b1 );
! 1570:
! 1571: c0 = a00^a40^a30^a20^a10;
! 1572: c1 = a31^a21^a11^a01^a41;
! 1573: c2 = a12^a02^a42^a32^a22;
! 1574: c3 = a43^a33^a23^a13^a03;
! 1575: c4 = a24^a14^a04^a44^a34;
! 1576: d0 = c4^ROL64(c1, 1);
! 1577: d1 = c0^ROL64(c2, 1);
! 1578: d2 = c1^ROL64(c3, 1);
! 1579: d3 = c2^ROL64(c4, 1);
! 1580: d4 = c3^ROL64(c0, 1);
! 1581:
! 1582: b0 = (a00^d0);
! 1583: b1 = ROL64((a21^d1), 44);
! 1584: b2 = ROL64((a42^d2), 43);
! 1585: b3 = ROL64((a13^d3), 21);
! 1586: b4 = ROL64((a34^d4), 14);
! 1587: a00 = b0 ^((~b1)& b2 );
! 1588: a00 ^= RC[i+2];
! 1589: a21 = b1 ^((~b2)& b3 );
! 1590: a42 = b2 ^((~b3)& b4 );
! 1591: a13 = b3 ^((~b4)& b0 );
! 1592: a34 = b4 ^((~b0)& b1 );
! 1593:
! 1594: b2 = ROL64((a30^d0), 3);
! 1595: b3 = ROL64((a01^d1), 45);
! 1596: b4 = ROL64((a22^d2), 61);
! 1597: b0 = ROL64((a43^d3), 28);
! 1598: b1 = ROL64((a14^d4), 20);
! 1599: a30 = b0 ^((~b1)& b2 );
! 1600: a01 = b1 ^((~b2)& b3 );
! 1601: a22 = b2 ^((~b3)& b4 );
! 1602: a43 = b3 ^((~b4)& b0 );
! 1603: a14 = b4 ^((~b0)& b1 );
! 1604:
! 1605: b4 = ROL64((a10^d0), 18);
! 1606: b0 = ROL64((a31^d1), 1);
! 1607: b1 = ROL64((a02^d2), 6);
! 1608: b2 = ROL64((a23^d3), 25);
! 1609: b3 = ROL64((a44^d4), 8);
! 1610: a10 = b0 ^((~b1)& b2 );
! 1611: a31 = b1 ^((~b2)& b3 );
! 1612: a02 = b2 ^((~b3)& b4 );
! 1613: a23 = b3 ^((~b4)& b0 );
! 1614: a44 = b4 ^((~b0)& b1 );
! 1615:
! 1616: b1 = ROL64((a40^d0), 36);
! 1617: b2 = ROL64((a11^d1), 10);
! 1618: b3 = ROL64((a32^d2), 15);
! 1619: b4 = ROL64((a03^d3), 56);
! 1620: b0 = ROL64((a24^d4), 27);
! 1621: a40 = b0 ^((~b1)& b2 );
! 1622: a11 = b1 ^((~b2)& b3 );
! 1623: a32 = b2 ^((~b3)& b4 );
! 1624: a03 = b3 ^((~b4)& b0 );
! 1625: a24 = b4 ^((~b0)& b1 );
! 1626:
! 1627: b3 = ROL64((a20^d0), 41);
! 1628: b4 = ROL64((a41^d1), 2);
! 1629: b0 = ROL64((a12^d2), 62);
! 1630: b1 = ROL64((a33^d3), 55);
! 1631: b2 = ROL64((a04^d4), 39);
! 1632: a20 = b0 ^((~b1)& b2 );
! 1633: a41 = b1 ^((~b2)& b3 );
! 1634: a12 = b2 ^((~b3)& b4 );
! 1635: a33 = b3 ^((~b4)& b0 );
! 1636: a04 = b4 ^((~b0)& b1 );
! 1637:
! 1638: c0 = a00^a30^a10^a40^a20;
! 1639: c1 = a21^a01^a31^a11^a41;
! 1640: c2 = a42^a22^a02^a32^a12;
! 1641: c3 = a13^a43^a23^a03^a33;
! 1642: c4 = a34^a14^a44^a24^a04;
! 1643: d0 = c4^ROL64(c1, 1);
! 1644: d1 = c0^ROL64(c2, 1);
! 1645: d2 = c1^ROL64(c3, 1);
! 1646: d3 = c2^ROL64(c4, 1);
! 1647: d4 = c3^ROL64(c0, 1);
! 1648:
! 1649: b0 = (a00^d0);
! 1650: b1 = ROL64((a01^d1), 44);
! 1651: b2 = ROL64((a02^d2), 43);
! 1652: b3 = ROL64((a03^d3), 21);
! 1653: b4 = ROL64((a04^d4), 14);
! 1654: a00 = b0 ^((~b1)& b2 );
! 1655: a00 ^= RC[i+3];
! 1656: a01 = b1 ^((~b2)& b3 );
! 1657: a02 = b2 ^((~b3)& b4 );
! 1658: a03 = b3 ^((~b4)& b0 );
! 1659: a04 = b4 ^((~b0)& b1 );
! 1660:
! 1661: b2 = ROL64((a10^d0), 3);
! 1662: b3 = ROL64((a11^d1), 45);
! 1663: b4 = ROL64((a12^d2), 61);
! 1664: b0 = ROL64((a13^d3), 28);
! 1665: b1 = ROL64((a14^d4), 20);
! 1666: a10 = b0 ^((~b1)& b2 );
! 1667: a11 = b1 ^((~b2)& b3 );
! 1668: a12 = b2 ^((~b3)& b4 );
! 1669: a13 = b3 ^((~b4)& b0 );
! 1670: a14 = b4 ^((~b0)& b1 );
! 1671:
! 1672: b4 = ROL64((a20^d0), 18);
! 1673: b0 = ROL64((a21^d1), 1);
! 1674: b1 = ROL64((a22^d2), 6);
! 1675: b2 = ROL64((a23^d3), 25);
! 1676: b3 = ROL64((a24^d4), 8);
! 1677: a20 = b0 ^((~b1)& b2 );
! 1678: a21 = b1 ^((~b2)& b3 );
! 1679: a22 = b2 ^((~b3)& b4 );
! 1680: a23 = b3 ^((~b4)& b0 );
! 1681: a24 = b4 ^((~b0)& b1 );
! 1682:
! 1683: b1 = ROL64((a30^d0), 36);
! 1684: b2 = ROL64((a31^d1), 10);
! 1685: b3 = ROL64((a32^d2), 15);
! 1686: b4 = ROL64((a33^d3), 56);
! 1687: b0 = ROL64((a34^d4), 27);
! 1688: a30 = b0 ^((~b1)& b2 );
! 1689: a31 = b1 ^((~b2)& b3 );
! 1690: a32 = b2 ^((~b3)& b4 );
! 1691: a33 = b3 ^((~b4)& b0 );
! 1692: a34 = b4 ^((~b0)& b1 );
! 1693:
! 1694: b3 = ROL64((a40^d0), 41);
! 1695: b4 = ROL64((a41^d1), 2);
! 1696: b0 = ROL64((a42^d2), 62);
! 1697: b1 = ROL64((a43^d3), 55);
! 1698: b2 = ROL64((a44^d4), 39);
! 1699: a40 = b0 ^((~b1)& b2 );
! 1700: a41 = b1 ^((~b2)& b3 );
! 1701: a42 = b2 ^((~b3)& b4 );
! 1702: a43 = b3 ^((~b4)& b0 );
! 1703: a44 = b4 ^((~b0)& b1 );
! 1704: }
! 1705: }
1.2 misho 1706:
1707: /*
1.4.2.2 ! misho 1708: ** Initialize a new hash. iSize determines the size of the hash
! 1709: ** in bits and should be one of 224, 256, 384, or 512. Or iSize
! 1710: ** can be zero to use the default hash size of 256 bits.
1.4 misho 1711: */
1.4.2.2 ! misho 1712: static void SHA3Init(SHA3Context *p, int iSize){
! 1713: memset(p, 0, sizeof(*p));
! 1714: if( iSize>=128 && iSize<=512 ){
! 1715: p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
! 1716: }else{
! 1717: p->nRate = (1600 - 2*256)/8;
! 1718: }
! 1719: #if SHA3_BYTEORDER==1234
! 1720: /* Known to be little-endian at compile-time. No-op */
! 1721: #elif SHA3_BYTEORDER==4321
! 1722: p->ixMask = 7; /* Big-endian */
! 1723: #else
! 1724: {
! 1725: static unsigned int one = 1;
! 1726: if( 1==*(unsigned char*)&one ){
! 1727: /* Little endian. No byte swapping. */
! 1728: p->ixMask = 0;
! 1729: }else{
! 1730: /* Big endian. Byte swap. */
! 1731: p->ixMask = 7;
! 1732: }
! 1733: }
! 1734: #endif
! 1735: }
1.4.2.1 misho 1736:
1737: /*
1.4.2.2 ! misho 1738: ** Make consecutive calls to the SHA3Update function to add new content
! 1739: ** to the hash
1.4.2.1 misho 1740: */
1.4.2.2 ! misho 1741: static void SHA3Update(
! 1742: SHA3Context *p,
! 1743: const unsigned char *aData,
! 1744: unsigned int nData
! 1745: ){
! 1746: unsigned int i = 0;
! 1747: #if SHA3_BYTEORDER==1234
! 1748: if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
! 1749: for(; i+7<nData; i+=8){
! 1750: p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
! 1751: p->nLoaded += 8;
! 1752: if( p->nLoaded>=p->nRate ){
! 1753: KeccakF1600Step(p);
! 1754: p->nLoaded = 0;
! 1755: }
! 1756: }
! 1757: }
! 1758: #endif
! 1759: for(; i<nData; i++){
! 1760: #if SHA3_BYTEORDER==1234
! 1761: p->u.x[p->nLoaded] ^= aData[i];
! 1762: #elif SHA3_BYTEORDER==4321
! 1763: p->u.x[p->nLoaded^0x07] ^= aData[i];
! 1764: #else
! 1765: p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
! 1766: #endif
! 1767: p->nLoaded++;
! 1768: if( p->nLoaded==p->nRate ){
! 1769: KeccakF1600Step(p);
! 1770: p->nLoaded = 0;
! 1771: }
! 1772: }
! 1773: }
1.4 misho 1774:
1775: /*
1.4.2.2 ! misho 1776: ** After all content has been added, invoke SHA3Final() to compute
! 1777: ** the final hash. The function returns a pointer to the binary
! 1778: ** hash value.
1.2 misho 1779: */
1.4.2.2 ! misho 1780: static unsigned char *SHA3Final(SHA3Context *p){
! 1781: unsigned int i;
! 1782: if( p->nLoaded==p->nRate-1 ){
! 1783: const unsigned char c1 = 0x86;
! 1784: SHA3Update(p, &c1, 1);
! 1785: }else{
! 1786: const unsigned char c2 = 0x06;
! 1787: const unsigned char c3 = 0x80;
! 1788: SHA3Update(p, &c2, 1);
! 1789: p->nLoaded = p->nRate - 1;
! 1790: SHA3Update(p, &c3, 1);
! 1791: }
! 1792: for(i=0; i<p->nRate; i++){
! 1793: p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
! 1794: }
! 1795: return &p->u.x[p->nRate];
1.2 misho 1796: }
1.4.2.2 ! misho 1797: /* End of the hashing logic
! 1798: *****************************************************************************/
1.2 misho 1799:
1800: /*
1.4.2.2 ! misho 1801: ** Implementation of the sha3(X,SIZE) function.
! 1802: **
! 1803: ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
! 1804: ** size is 256. If X is a BLOB, it is hashed as is.
! 1805: ** For all other non-NULL types of input, X is converted into a UTF-8 string
! 1806: ** and the string is hashed without the trailing 0x00 terminator. The hash
! 1807: ** of a NULL value is NULL.
1.2 misho 1808: */
1.4.2.2 ! misho 1809: static void sha3Func(
! 1810: sqlite3_context *context,
! 1811: int argc,
! 1812: sqlite3_value **argv
! 1813: ){
! 1814: SHA3Context cx;
! 1815: int eType = sqlite3_value_type(argv[0]);
! 1816: int nByte = sqlite3_value_bytes(argv[0]);
! 1817: int iSize;
! 1818: if( argc==1 ){
! 1819: iSize = 256;
! 1820: }else{
! 1821: iSize = sqlite3_value_int(argv[1]);
! 1822: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
! 1823: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
! 1824: "384 512", -1);
! 1825: return;
! 1826: }
! 1827: }
! 1828: if( eType==SQLITE_NULL ) return;
! 1829: SHA3Init(&cx, iSize);
! 1830: if( eType==SQLITE_BLOB ){
! 1831: SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
! 1832: }else{
! 1833: SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
! 1834: }
! 1835: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
1.2 misho 1836: }
1837:
1.4.2.2 ! misho 1838: /* Compute a string using sqlite3_vsnprintf() with a maximum length
! 1839: ** of 50 bytes and add it to the hash.
1.4.2.1 misho 1840: */
1.4.2.2 ! misho 1841: static void hash_step_vformat(
! 1842: SHA3Context *p, /* Add content to this context */
! 1843: const char *zFormat,
! 1844: ...
1.4.2.1 misho 1845: ){
1.4.2.2 ! misho 1846: va_list ap;
! 1847: int n;
! 1848: char zBuf[50];
! 1849: va_start(ap, zFormat);
! 1850: sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
! 1851: va_end(ap);
! 1852: n = (int)strlen(zBuf);
! 1853: SHA3Update(p, (unsigned char*)zBuf, n);
1.4.2.1 misho 1854: }
1855:
1856: /*
1.4.2.2 ! misho 1857: ** Implementation of the sha3_query(SQL,SIZE) function.
1.4.2.1 misho 1858: **
1.4.2.2 ! misho 1859: ** This function compiles and runs the SQL statement(s) given in the
! 1860: ** argument. The results are hashed using a SIZE-bit SHA3. The default
! 1861: ** size is 256.
! 1862: **
! 1863: ** The format of the byte stream that is hashed is summarized as follows:
! 1864: **
! 1865: ** S<n>:<sql>
! 1866: ** R
! 1867: ** N
! 1868: ** I<int>
! 1869: ** F<ieee-float>
! 1870: ** B<size>:<bytes>
! 1871: ** T<size>:<text>
! 1872: **
! 1873: ** <sql> is the original SQL text for each statement run and <n> is
! 1874: ** the size of that text. The SQL text is UTF-8. A single R character
! 1875: ** occurs before the start of each row. N means a NULL value.
! 1876: ** I mean an 8-byte little-endian integer <int>. F is a floating point
! 1877: ** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
! 1878: ** B means blobs of <size> bytes. T means text rendered as <size>
! 1879: ** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
! 1880: ** text integers.
! 1881: **
! 1882: ** For each SQL statement in the X input, there is one S segment. Each
! 1883: ** S segment is followed by zero or more R segments, one for each row in the
! 1884: ** result set. After each R, there are one or more N, I, F, B, or T segments,
! 1885: ** one for each column in the result set. Segments are concatentated directly
! 1886: ** with no delimiters of any kind.
1.2 misho 1887: */
1.4.2.2 ! misho 1888: static void sha3QueryFunc(
! 1889: sqlite3_context *context,
! 1890: int argc,
! 1891: sqlite3_value **argv
! 1892: ){
! 1893: sqlite3 *db = sqlite3_context_db_handle(context);
! 1894: const char *zSql = (const char*)sqlite3_value_text(argv[0]);
! 1895: sqlite3_stmt *pStmt = 0;
! 1896: int nCol; /* Number of columns in the result set */
! 1897: int i; /* Loop counter */
! 1898: int rc;
! 1899: int n;
! 1900: const char *z;
! 1901: SHA3Context cx;
! 1902: int iSize;
! 1903:
! 1904: if( argc==1 ){
! 1905: iSize = 256;
1.4.2.1 misho 1906: }else{
1.4.2.2 ! misho 1907: iSize = sqlite3_value_int(argv[1]);
! 1908: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
! 1909: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
! 1910: "384 512", -1);
! 1911: return;
1.4.2.1 misho 1912: }
1.2 misho 1913: }
1.4.2.2 ! misho 1914: if( zSql==0 ) return;
! 1915: SHA3Init(&cx, iSize);
! 1916: while( zSql[0] ){
! 1917: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
! 1918: if( rc ){
! 1919: char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
! 1920: zSql, sqlite3_errmsg(db));
! 1921: sqlite3_finalize(pStmt);
! 1922: sqlite3_result_error(context, zMsg, -1);
! 1923: sqlite3_free(zMsg);
! 1924: return;
! 1925: }
! 1926: if( !sqlite3_stmt_readonly(pStmt) ){
! 1927: char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
! 1928: sqlite3_finalize(pStmt);
! 1929: sqlite3_result_error(context, zMsg, -1);
! 1930: sqlite3_free(zMsg);
! 1931: return;
! 1932: }
! 1933: nCol = sqlite3_column_count(pStmt);
! 1934: z = sqlite3_sql(pStmt);
! 1935: n = (int)strlen(z);
! 1936: hash_step_vformat(&cx,"S%d:",n);
! 1937: SHA3Update(&cx,(unsigned char*)z,n);
1.4.2.1 misho 1938:
1.4.2.2 ! misho 1939: /* Compute a hash over the result of the query */
! 1940: while( SQLITE_ROW==sqlite3_step(pStmt) ){
! 1941: SHA3Update(&cx,(const unsigned char*)"R",1);
! 1942: for(i=0; i<nCol; i++){
! 1943: switch( sqlite3_column_type(pStmt,i) ){
! 1944: case SQLITE_NULL: {
! 1945: SHA3Update(&cx, (const unsigned char*)"N",1);
! 1946: break;
! 1947: }
! 1948: case SQLITE_INTEGER: {
! 1949: sqlite3_uint64 u;
! 1950: int j;
! 1951: unsigned char x[9];
! 1952: sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
! 1953: memcpy(&u, &v, 8);
! 1954: for(j=8; j>=1; j--){
! 1955: x[j] = u & 0xff;
! 1956: u >>= 8;
! 1957: }
! 1958: x[0] = 'I';
! 1959: SHA3Update(&cx, x, 9);
! 1960: break;
! 1961: }
! 1962: case SQLITE_FLOAT: {
! 1963: sqlite3_uint64 u;
! 1964: int j;
! 1965: unsigned char x[9];
! 1966: double r = sqlite3_column_double(pStmt,i);
! 1967: memcpy(&u, &r, 8);
! 1968: for(j=8; j>=1; j--){
! 1969: x[j] = u & 0xff;
! 1970: u >>= 8;
! 1971: }
! 1972: x[0] = 'F';
! 1973: SHA3Update(&cx,x,9);
! 1974: break;
! 1975: }
! 1976: case SQLITE_TEXT: {
! 1977: int n2 = sqlite3_column_bytes(pStmt, i);
! 1978: const unsigned char *z2 = sqlite3_column_text(pStmt, i);
! 1979: hash_step_vformat(&cx,"T%d:",n2);
! 1980: SHA3Update(&cx, z2, n2);
! 1981: break;
! 1982: }
! 1983: case SQLITE_BLOB: {
! 1984: int n2 = sqlite3_column_bytes(pStmt, i);
! 1985: const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
! 1986: hash_step_vformat(&cx,"B%d:",n2);
! 1987: SHA3Update(&cx, z2, n2);
! 1988: break;
! 1989: }
! 1990: }
1.4.2.1 misho 1991: }
1.2 misho 1992: }
1.4.2.2 ! misho 1993: sqlite3_finalize(pStmt);
1.2 misho 1994: }
1.4.2.2 ! misho 1995: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
1.2 misho 1996: }
1997:
1.4.2.2 ! misho 1998:
! 1999: #ifdef _WIN32
! 2000:
! 2001: #endif
! 2002: int sqlite3_shathree_init(
! 2003: sqlite3 *db,
! 2004: char **pzErrMsg,
! 2005: const sqlite3_api_routines *pApi
! 2006: ){
! 2007: int rc = SQLITE_OK;
! 2008: SQLITE_EXTENSION_INIT2(pApi);
! 2009: (void)pzErrMsg; /* Unused parameter */
! 2010: rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
! 2011: sha3Func, 0, 0);
! 2012: if( rc==SQLITE_OK ){
! 2013: rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
! 2014: sha3Func, 0, 0);
1.2 misho 2015: }
1.4.2.2 ! misho 2016: if( rc==SQLITE_OK ){
! 2017: rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
! 2018: sha3QueryFunc, 0, 0);
! 2019: }
! 2020: if( rc==SQLITE_OK ){
! 2021: rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
! 2022: sha3QueryFunc, 0, 0);
! 2023: }
! 2024: return rc;
1.2 misho 2025: }
2026:
1.4.2.2 ! misho 2027: /************************* End ../ext/misc/shathree.c ********************/
! 2028: /************************* Begin ../ext/misc/fileio.c ******************/
1.2 misho 2029: /*
1.4.2.2 ! misho 2030: ** 2014-06-13
! 2031: **
! 2032: ** The author disclaims copyright to this source code. In place of
! 2033: ** a legal notice, here is a blessing:
! 2034: **
! 2035: ** May you do good and not evil.
! 2036: ** May you find forgiveness for yourself and forgive others.
! 2037: ** May you share freely, never taking more than you give.
! 2038: **
! 2039: ******************************************************************************
! 2040: **
! 2041: ** This SQLite extension implements SQL functions readfile() and
! 2042: ** writefile(), and eponymous virtual type "fsdir".
! 2043: **
! 2044: ** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
! 2045: **
! 2046: ** If neither of the optional arguments is present, then this UDF
! 2047: ** function writes blob DATA to file FILE. If successful, the number
! 2048: ** of bytes written is returned. If an error occurs, NULL is returned.
! 2049: **
! 2050: ** If the first option argument - MODE - is present, then it must
! 2051: ** be passed an integer value that corresponds to a POSIX mode
! 2052: ** value (file type + permissions, as returned in the stat.st_mode
! 2053: ** field by the stat() system call). Three types of files may
! 2054: ** be written/created:
! 2055: **
! 2056: ** regular files: (mode & 0170000)==0100000
! 2057: ** symbolic links: (mode & 0170000)==0120000
! 2058: ** directories: (mode & 0170000)==0040000
! 2059: **
! 2060: ** For a directory, the DATA is ignored. For a symbolic link, it is
! 2061: ** interpreted as text and used as the target of the link. For a
! 2062: ** regular file, it is interpreted as a blob and written into the
! 2063: ** named file. Regardless of the type of file, its permissions are
! 2064: ** set to (mode & 0777) before returning.
! 2065: **
! 2066: ** If the optional MTIME argument is present, then it is interpreted
! 2067: ** as an integer - the number of seconds since the unix epoch. The
! 2068: ** modification-time of the target file is set to this value before
! 2069: ** returning.
! 2070: **
! 2071: ** If three or more arguments are passed to this function and an
! 2072: ** error is encountered, an exception is raised.
! 2073: **
! 2074: ** READFILE(FILE):
! 2075: **
! 2076: ** Read and return the contents of file FILE (type blob) from disk.
! 2077: **
! 2078: ** FSDIR:
! 2079: **
! 2080: ** Used as follows:
! 2081: **
! 2082: ** SELECT * FROM fsdir($path [, $dir]);
! 2083: **
! 2084: ** Parameter $path is an absolute or relative pathname. If the file that it
! 2085: ** refers to does not exist, it is an error. If the path refers to a regular
! 2086: ** file or symbolic link, it returns a single row. Or, if the path refers
! 2087: ** to a directory, it returns one row for the directory, and one row for each
! 2088: ** file within the hierarchy rooted at $path.
! 2089: **
! 2090: ** Each row has the following columns:
! 2091: **
! 2092: ** name: Path to file or directory (text value).
! 2093: ** mode: Value of stat.st_mode for directory entry (an integer).
! 2094: ** mtime: Value of stat.st_mtime for directory entry (an integer).
! 2095: ** data: For a regular file, a blob containing the file data. For a
! 2096: ** symlink, a text value containing the text of the link. For a
! 2097: ** directory, NULL.
! 2098: **
! 2099: ** If a non-NULL value is specified for the optional $dir parameter and
! 2100: ** $path is a relative path, then $path is interpreted relative to $dir.
! 2101: ** And the paths returned in the "name" column of the table are also
! 2102: ** relative to directory $dir.
1.2 misho 2103: */
1.4.2.2 ! misho 2104: /* #include "sqlite3ext.h" */
! 2105: SQLITE_EXTENSION_INIT1
! 2106: #include <stdio.h>
! 2107: #include <string.h>
! 2108: #include <assert.h>
! 2109:
! 2110: #include <sys/types.h>
! 2111: #include <sys/stat.h>
! 2112: #include <fcntl.h>
! 2113: #if !defined(_WIN32) && !defined(WIN32)
! 2114: # include <unistd.h>
! 2115: # include <dirent.h>
! 2116: # include <utime.h>
! 2117: # include <sys/time.h>
! 2118: #else
! 2119: # include "windows.h"
! 2120: # include <io.h>
! 2121: # include <direct.h>
! 2122: /* # include "test_windirent.h" */
! 2123: # define dirent DIRENT
! 2124: # ifndef chmod
! 2125: # define chmod _chmod
! 2126: # endif
! 2127: # ifndef stat
! 2128: # define stat _stat
! 2129: # endif
! 2130: # define mkdir(path,mode) _mkdir(path)
! 2131: # define lstat(path,buf) stat(path,buf)
! 2132: #endif
! 2133: #include <time.h>
! 2134: #include <errno.h>
! 2135:
1.2 misho 2136:
2137: /*
1.4.2.2 ! misho 2138: ** Structure of the fsdir() table-valued function
1.2 misho 2139: */
1.4.2.2 ! misho 2140: /* 0 1 2 3 4 5 */
! 2141: #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
! 2142: #define FSDIR_COLUMN_NAME 0 /* Name of the file */
! 2143: #define FSDIR_COLUMN_MODE 1 /* Access mode */
! 2144: #define FSDIR_COLUMN_MTIME 2 /* Last modification time */
! 2145: #define FSDIR_COLUMN_DATA 3 /* File content */
! 2146: #define FSDIR_COLUMN_PATH 4 /* Path to top of search */
! 2147: #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
! 2148:
1.2 misho 2149:
2150: /*
1.4.2.2 ! misho 2151: ** Set the result stored by context ctx to a blob containing the
! 2152: ** contents of file zName. Or, leave the result unchanged (NULL)
! 2153: ** if the file does not exist or is unreadable.
! 2154: **
! 2155: ** If the file exceeds the SQLite blob size limit, through an
! 2156: ** SQLITE_TOOBIG error.
! 2157: **
! 2158: ** Throw an SQLITE_IOERR if there are difficulties pulling the file
! 2159: ** off of disk.
1.2 misho 2160: */
1.4.2.2 ! misho 2161: static void readFileContents(sqlite3_context *ctx, const char *zName){
! 2162: FILE *in;
! 2163: sqlite3_int64 nIn;
! 2164: void *pBuf;
! 2165: sqlite3 *db;
! 2166: int mxBlob;
! 2167:
! 2168: in = fopen(zName, "rb");
! 2169: if( in==0 ){
! 2170: /* File does not exist or is unreadable. Leave the result set to NULL. */
! 2171: return;
1.2 misho 2172: }
1.4.2.2 ! misho 2173: fseek(in, 0, SEEK_END);
! 2174: nIn = ftell(in);
! 2175: rewind(in);
! 2176: db = sqlite3_context_db_handle(ctx);
! 2177: mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
! 2178: if( nIn>mxBlob ){
! 2179: sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
! 2180: fclose(in);
! 2181: return;
! 2182: }
! 2183: pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
! 2184: if( pBuf==0 ){
! 2185: sqlite3_result_error_nomem(ctx);
! 2186: fclose(in);
! 2187: return;
! 2188: }
! 2189: if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
! 2190: sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
! 2191: }else{
! 2192: sqlite3_result_error_code(ctx, SQLITE_IOERR);
! 2193: sqlite3_free(pBuf);
1.2 misho 2194: }
1.4.2.2 ! misho 2195: fclose(in);
1.2 misho 2196: }
2197:
2198: /*
1.4.2.2 ! misho 2199: ** Implementation of the "readfile(X)" SQL function. The entire content
! 2200: ** of the file named X is read and returned as a BLOB. NULL is returned
! 2201: ** if the file does not exist or is unreadable.
1.2 misho 2202: */
1.4.2.2 ! misho 2203: static void readfileFunc(
! 2204: sqlite3_context *context,
! 2205: int argc,
! 2206: sqlite3_value **argv
! 2207: ){
! 2208: const char *zName;
! 2209: (void)(argc); /* Unused parameter */
! 2210: zName = (const char*)sqlite3_value_text(argv[0]);
! 2211: if( zName==0 ) return;
! 2212: readFileContents(context, zName);
1.2 misho 2213: }
2214:
2215: /*
1.4.2.2 ! misho 2216: ** Set the error message contained in context ctx to the results of
! 2217: ** vprintf(zFmt, ...).
1.4 misho 2218: */
1.4.2.2 ! misho 2219: static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
! 2220: char *zMsg = 0;
! 2221: va_list ap;
! 2222: va_start(ap, zFmt);
! 2223: zMsg = sqlite3_vmprintf(zFmt, ap);
! 2224: sqlite3_result_error(ctx, zMsg, -1);
! 2225: sqlite3_free(zMsg);
! 2226: va_end(ap);
! 2227: }
! 2228:
! 2229: #if defined(_WIN32)
! 2230: /*
! 2231: ** This function is designed to convert a Win32 FILETIME structure into the
! 2232: ** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
! 2233: */
! 2234: static sqlite3_uint64 fileTimeToUnixTime(
! 2235: LPFILETIME pFileTime
1.4 misho 2236: ){
1.4.2.2 ! misho 2237: SYSTEMTIME epochSystemTime;
! 2238: ULARGE_INTEGER epochIntervals;
! 2239: FILETIME epochFileTime;
! 2240: ULARGE_INTEGER fileIntervals;
! 2241:
! 2242: memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
! 2243: epochSystemTime.wYear = 1970;
! 2244: epochSystemTime.wMonth = 1;
! 2245: epochSystemTime.wDay = 1;
! 2246: SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
! 2247: epochIntervals.LowPart = epochFileTime.dwLowDateTime;
! 2248: epochIntervals.HighPart = epochFileTime.dwHighDateTime;
! 2249:
! 2250: fileIntervals.LowPart = pFileTime->dwLowDateTime;
! 2251: fileIntervals.HighPart = pFileTime->dwHighDateTime;
! 2252:
! 2253: return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
! 2254: }
! 2255:
! 2256: /*
! 2257: ** This function attempts to normalize the time values found in the stat()
! 2258: ** buffer to UTC. This is necessary on Win32, where the runtime library
! 2259: ** appears to return these values as local times.
! 2260: */
! 2261: static void statTimesToUtc(
! 2262: const char *zPath,
! 2263: struct stat *pStatBuf
! 2264: ){
! 2265: HANDLE hFindFile;
! 2266: WIN32_FIND_DATAW fd;
! 2267: LPWSTR zUnicodeName;
! 2268: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
! 2269: zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
! 2270: if( zUnicodeName ){
! 2271: memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
! 2272: hFindFile = FindFirstFileW(zUnicodeName, &fd);
! 2273: if( hFindFile!=NULL ){
! 2274: pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
! 2275: pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
! 2276: pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
! 2277: FindClose(hFindFile);
1.4 misho 2278: }
1.4.2.2 ! misho 2279: sqlite3_free(zUnicodeName);
1.4 misho 2280: }
2281: }
1.4.2.1 misho 2282: #endif
2283:
2284: /*
1.4.2.2 ! misho 2285: ** This function is used in place of stat(). On Windows, special handling
! 2286: ** is required in order for the included time to be returned as UTC. On all
! 2287: ** other systems, this function simply calls stat().
1.4.2.1 misho 2288: */
1.4.2.2 ! misho 2289: static int fileStat(
! 2290: const char *zPath,
! 2291: struct stat *pStatBuf
! 2292: ){
! 2293: #if defined(_WIN32)
! 2294: int rc = stat(zPath, pStatBuf);
! 2295: if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
! 2296: return rc;
! 2297: #else
! 2298: return stat(zPath, pStatBuf);
! 2299: #endif
1.4.2.1 misho 2300: }
1.4.2.2 ! misho 2301:
! 2302: /*
! 2303: ** This function is used in place of lstat(). On Windows, special handling
! 2304: ** is required in order for the included time to be returned as UTC. On all
! 2305: ** other systems, this function simply calls lstat().
! 2306: */
! 2307: static int fileLinkStat(
! 2308: const char *zPath,
! 2309: struct stat *pStatBuf
! 2310: ){
! 2311: #if defined(_WIN32)
! 2312: int rc = lstat(zPath, pStatBuf);
! 2313: if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
! 2314: return rc;
! 2315: #else
! 2316: return lstat(zPath, pStatBuf);
! 2317: #endif
1.4.2.1 misho 2318: }
1.4 misho 2319:
2320: /*
1.4.2.2 ! misho 2321: ** Argument zFile is the name of a file that will be created and/or written
! 2322: ** by SQL function writefile(). This function ensures that the directory
! 2323: ** zFile will be written to exists, creating it if required. The permissions
! 2324: ** for any path components created by this function are set in accordance
! 2325: ** with the current umask.
! 2326: **
! 2327: ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
! 2328: ** SQLITE_OK is returned if the directory is successfully created, or
! 2329: ** SQLITE_ERROR otherwise.
1.2 misho 2330: */
1.4.2.2 ! misho 2331: static int makeDirectory(
! 2332: const char *zFile
1.4 misho 2333: ){
1.4.2.2 ! misho 2334: char *zCopy = sqlite3_mprintf("%s", zFile);
! 2335: int rc = SQLITE_OK;
1.2 misho 2336:
1.4.2.2 ! misho 2337: if( zCopy==0 ){
! 2338: rc = SQLITE_NOMEM;
! 2339: }else{
! 2340: int nCopy = (int)strlen(zCopy);
! 2341: int i = 1;
! 2342:
! 2343: while( rc==SQLITE_OK ){
! 2344: struct stat sStat;
! 2345: int rc2;
! 2346:
! 2347: for(; zCopy[i]!='/' && i<nCopy; i++);
! 2348: if( i==nCopy ) break;
! 2349: zCopy[i] = '\0';
! 2350:
! 2351: rc2 = fileStat(zCopy, &sStat);
! 2352: if( rc2!=0 ){
! 2353: if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
1.4 misho 2354: }else{
1.4.2.2 ! misho 2355: if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
1.4 misho 2356: }
1.4.2.2 ! misho 2357: zCopy[i] = '/';
! 2358: i++;
! 2359: }
! 2360:
! 2361: sqlite3_free(zCopy);
! 2362: }
! 2363:
! 2364: return rc;
! 2365: }
! 2366:
! 2367: /*
! 2368: ** This function does the work for the writefile() UDF. Refer to
! 2369: ** header comments at the top of this file for details.
! 2370: */
! 2371: static int writeFile(
! 2372: sqlite3_context *pCtx, /* Context to return bytes written in */
! 2373: const char *zFile, /* File to write */
! 2374: sqlite3_value *pData, /* Data to write */
! 2375: mode_t mode, /* MODE parameter passed to writefile() */
! 2376: sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
! 2377: ){
! 2378: #if !defined(_WIN32) && !defined(WIN32)
! 2379: if( S_ISLNK(mode) ){
! 2380: const char *zTo = (const char*)sqlite3_value_text(pData);
! 2381: if( symlink(zTo, zFile)<0 ) return 1;
! 2382: }else
! 2383: #endif
! 2384: {
! 2385: if( S_ISDIR(mode) ){
! 2386: if( mkdir(zFile, mode) ){
! 2387: /* The mkdir() call to create the directory failed. This might not
! 2388: ** be an error though - if there is already a directory at the same
! 2389: ** path and either the permissions already match or can be changed
! 2390: ** to do so using chmod(), it is not an error. */
! 2391: struct stat sStat;
! 2392: if( errno!=EEXIST
! 2393: || 0!=fileStat(zFile, &sStat)
! 2394: || !S_ISDIR(sStat.st_mode)
! 2395: || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
! 2396: ){
! 2397: return 1;
1.2 misho 2398: }
2399: }
1.4.2.2 ! misho 2400: }else{
! 2401: sqlite3_int64 nWrite = 0;
! 2402: const char *z;
! 2403: int rc = 0;
! 2404: FILE *out = fopen(zFile, "wb");
! 2405: if( out==0 ) return 1;
! 2406: z = (const char*)sqlite3_value_blob(pData);
! 2407: if( z ){
! 2408: sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
! 2409: nWrite = sqlite3_value_bytes(pData);
! 2410: if( nWrite!=n ){
! 2411: rc = 1;
1.4 misho 2412: }
2413: }
1.4.2.2 ! misho 2414: fclose(out);
! 2415: if( rc==0 && mode && chmod(zFile, mode & 0777) ){
! 2416: rc = 1;
! 2417: }
! 2418: if( rc ) return 2;
! 2419: sqlite3_result_int64(pCtx, nWrite);
1.4 misho 2420: }
1.4.2.2 ! misho 2421: }
! 2422:
! 2423: if( mtime>=0 ){
! 2424: #if defined(_WIN32)
! 2425: /* Windows */
! 2426: FILETIME lastAccess;
! 2427: FILETIME lastWrite;
! 2428: SYSTEMTIME currentTime;
! 2429: LONGLONG intervals;
! 2430: HANDLE hFile;
! 2431: LPWSTR zUnicodeName;
! 2432: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
! 2433:
! 2434: GetSystemTime(¤tTime);
! 2435: SystemTimeToFileTime(¤tTime, &lastAccess);
! 2436: intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
! 2437: lastWrite.dwLowDateTime = (DWORD)intervals;
! 2438: lastWrite.dwHighDateTime = intervals >> 32;
! 2439: zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
! 2440: if( zUnicodeName==0 ){
! 2441: return 1;
1.4 misho 2442: }
1.4.2.2 ! misho 2443: hFile = CreateFileW(
! 2444: zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
! 2445: FILE_FLAG_BACKUP_SEMANTICS, NULL
! 2446: );
! 2447: sqlite3_free(zUnicodeName);
! 2448: if( hFile!=INVALID_HANDLE_VALUE ){
! 2449: BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
! 2450: CloseHandle(hFile);
! 2451: return !bResult;
! 2452: }else{
! 2453: return 1;
! 2454: }
! 2455: #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
! 2456: /* Recent unix */
! 2457: struct timespec times[2];
! 2458: times[0].tv_nsec = times[1].tv_nsec = 0;
! 2459: times[0].tv_sec = time(0);
! 2460: times[1].tv_sec = mtime;
! 2461: if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
! 2462: return 1;
! 2463: }
! 2464: #else
! 2465: /* Legacy unix */
! 2466: struct timeval times[2];
! 2467: times[0].tv_usec = times[1].tv_usec = 0;
! 2468: times[0].tv_sec = time(0);
! 2469: times[1].tv_sec = mtime;
! 2470: if( utimes(zFile, times) ){
! 2471: return 1;
! 2472: }
! 2473: #endif
! 2474: }
! 2475:
! 2476: return 0;
! 2477: }
! 2478:
! 2479: /*
! 2480: ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
! 2481: ** Refer to header comments at the top of this file for details.
! 2482: */
! 2483: static void writefileFunc(
! 2484: sqlite3_context *context,
! 2485: int argc,
! 2486: sqlite3_value **argv
! 2487: ){
! 2488: const char *zFile;
! 2489: mode_t mode = 0;
! 2490: int res;
! 2491: sqlite3_int64 mtime = -1;
! 2492:
! 2493: if( argc<2 || argc>4 ){
! 2494: sqlite3_result_error(context,
! 2495: "wrong number of arguments to function writefile()", -1
! 2496: );
! 2497: return;
! 2498: }
! 2499:
! 2500: zFile = (const char*)sqlite3_value_text(argv[0]);
! 2501: if( zFile==0 ) return;
! 2502: if( argc>=3 ){
! 2503: mode = (mode_t)sqlite3_value_int(argv[2]);
! 2504: }
! 2505: if( argc==4 ){
! 2506: mtime = sqlite3_value_int64(argv[3]);
! 2507: }
! 2508:
! 2509: res = writeFile(context, zFile, argv[1], mode, mtime);
! 2510: if( res==1 && errno==ENOENT ){
! 2511: if( makeDirectory(zFile)==SQLITE_OK ){
! 2512: res = writeFile(context, zFile, argv[1], mode, mtime);
! 2513: }
! 2514: }
! 2515:
! 2516: if( argc>2 && res!=0 ){
! 2517: if( S_ISLNK(mode) ){
! 2518: ctxErrorMsg(context, "failed to create symlink: %s", zFile);
! 2519: }else if( S_ISDIR(mode) ){
! 2520: ctxErrorMsg(context, "failed to create directory: %s", zFile);
! 2521: }else{
! 2522: ctxErrorMsg(context, "failed to write file: %s", zFile);
! 2523: }
! 2524: }
! 2525: }
! 2526:
! 2527: /*
! 2528: ** SQL function: lsmode(MODE)
! 2529: **
! 2530: ** Given a numberic st_mode from stat(), convert it into a human-readable
! 2531: ** text string in the style of "ls -l".
! 2532: */
! 2533: static void lsModeFunc(
! 2534: sqlite3_context *context,
! 2535: int argc,
! 2536: sqlite3_value **argv
! 2537: ){
! 2538: int i;
! 2539: int iMode = sqlite3_value_int(argv[0]);
! 2540: char z[16];
! 2541: (void)argc;
! 2542: if( S_ISLNK(iMode) ){
! 2543: z[0] = 'l';
! 2544: }else if( S_ISREG(iMode) ){
! 2545: z[0] = '-';
! 2546: }else if( S_ISDIR(iMode) ){
! 2547: z[0] = 'd';
! 2548: }else{
! 2549: z[0] = '?';
! 2550: }
! 2551: for(i=0; i<3; i++){
! 2552: int m = (iMode >> ((2-i)*3));
! 2553: char *a = &z[1 + i*3];
! 2554: a[0] = (m & 0x4) ? 'r' : '-';
! 2555: a[1] = (m & 0x2) ? 'w' : '-';
! 2556: a[2] = (m & 0x1) ? 'x' : '-';
! 2557: }
! 2558: z[10] = '\0';
! 2559: sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
! 2560: }
! 2561:
! 2562: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 2563:
! 2564: /*
! 2565: ** Cursor type for recursively iterating through a directory structure.
! 2566: */
! 2567: typedef struct fsdir_cursor fsdir_cursor;
! 2568: typedef struct FsdirLevel FsdirLevel;
! 2569:
! 2570: struct FsdirLevel {
! 2571: DIR *pDir; /* From opendir() */
! 2572: char *zDir; /* Name of directory (nul-terminated) */
! 2573: };
! 2574:
! 2575: struct fsdir_cursor {
! 2576: sqlite3_vtab_cursor base; /* Base class - must be first */
! 2577:
! 2578: int nLvl; /* Number of entries in aLvl[] array */
! 2579: int iLvl; /* Index of current entry */
! 2580: FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
! 2581:
! 2582: const char *zBase;
! 2583: int nBase;
! 2584:
! 2585: struct stat sStat; /* Current lstat() results */
! 2586: char *zPath; /* Path to current entry */
! 2587: sqlite3_int64 iRowid; /* Current rowid */
! 2588: };
! 2589:
! 2590: typedef struct fsdir_tab fsdir_tab;
! 2591: struct fsdir_tab {
! 2592: sqlite3_vtab base; /* Base class - must be first */
! 2593: };
! 2594:
! 2595: /*
! 2596: ** Construct a new fsdir virtual table object.
! 2597: */
! 2598: static int fsdirConnect(
! 2599: sqlite3 *db,
! 2600: void *pAux,
! 2601: int argc, const char *const*argv,
! 2602: sqlite3_vtab **ppVtab,
! 2603: char **pzErr
! 2604: ){
! 2605: fsdir_tab *pNew = 0;
! 2606: int rc;
! 2607: (void)pAux;
! 2608: (void)argc;
! 2609: (void)argv;
! 2610: (void)pzErr;
! 2611: rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
! 2612: if( rc==SQLITE_OK ){
! 2613: pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
! 2614: if( pNew==0 ) return SQLITE_NOMEM;
! 2615: memset(pNew, 0, sizeof(*pNew));
! 2616: }
! 2617: *ppVtab = (sqlite3_vtab*)pNew;
! 2618: return rc;
! 2619: }
! 2620:
! 2621: /*
! 2622: ** This method is the destructor for fsdir vtab objects.
! 2623: */
! 2624: static int fsdirDisconnect(sqlite3_vtab *pVtab){
! 2625: sqlite3_free(pVtab);
! 2626: return SQLITE_OK;
! 2627: }
! 2628:
! 2629: /*
! 2630: ** Constructor for a new fsdir_cursor object.
! 2631: */
! 2632: static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
! 2633: fsdir_cursor *pCur;
! 2634: (void)p;
! 2635: pCur = sqlite3_malloc( sizeof(*pCur) );
! 2636: if( pCur==0 ) return SQLITE_NOMEM;
! 2637: memset(pCur, 0, sizeof(*pCur));
! 2638: pCur->iLvl = -1;
! 2639: *ppCursor = &pCur->base;
! 2640: return SQLITE_OK;
! 2641: }
! 2642:
! 2643: /*
! 2644: ** Reset a cursor back to the state it was in when first returned
! 2645: ** by fsdirOpen().
! 2646: */
! 2647: static void fsdirResetCursor(fsdir_cursor *pCur){
! 2648: int i;
! 2649: for(i=0; i<=pCur->iLvl; i++){
! 2650: FsdirLevel *pLvl = &pCur->aLvl[i];
! 2651: if( pLvl->pDir ) closedir(pLvl->pDir);
! 2652: sqlite3_free(pLvl->zDir);
! 2653: }
! 2654: sqlite3_free(pCur->zPath);
! 2655: sqlite3_free(pCur->aLvl);
! 2656: pCur->aLvl = 0;
! 2657: pCur->zPath = 0;
! 2658: pCur->zBase = 0;
! 2659: pCur->nBase = 0;
! 2660: pCur->nLvl = 0;
! 2661: pCur->iLvl = -1;
! 2662: pCur->iRowid = 1;
! 2663: }
! 2664:
! 2665: /*
! 2666: ** Destructor for an fsdir_cursor.
! 2667: */
! 2668: static int fsdirClose(sqlite3_vtab_cursor *cur){
! 2669: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2670:
! 2671: fsdirResetCursor(pCur);
! 2672: sqlite3_free(pCur);
! 2673: return SQLITE_OK;
! 2674: }
! 2675:
! 2676: /*
! 2677: ** Set the error message for the virtual table associated with cursor
! 2678: ** pCur to the results of vprintf(zFmt, ...).
! 2679: */
! 2680: static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
! 2681: va_list ap;
! 2682: va_start(ap, zFmt);
! 2683: pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 2684: va_end(ap);
! 2685: }
! 2686:
! 2687:
! 2688: /*
! 2689: ** Advance an fsdir_cursor to its next row of output.
! 2690: */
! 2691: static int fsdirNext(sqlite3_vtab_cursor *cur){
! 2692: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2693: mode_t m = pCur->sStat.st_mode;
! 2694:
! 2695: pCur->iRowid++;
! 2696: if( S_ISDIR(m) ){
! 2697: /* Descend into this directory */
! 2698: int iNew = pCur->iLvl + 1;
! 2699: FsdirLevel *pLvl;
! 2700: if( iNew>=pCur->nLvl ){
! 2701: int nNew = iNew+1;
! 2702: sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
! 2703: FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
! 2704: if( aNew==0 ) return SQLITE_NOMEM;
! 2705: memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
! 2706: pCur->aLvl = aNew;
! 2707: pCur->nLvl = nNew;
! 2708: }
! 2709: pCur->iLvl = iNew;
! 2710: pLvl = &pCur->aLvl[iNew];
! 2711:
! 2712: pLvl->zDir = pCur->zPath;
! 2713: pCur->zPath = 0;
! 2714: pLvl->pDir = opendir(pLvl->zDir);
! 2715: if( pLvl->pDir==0 ){
! 2716: fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
! 2717: return SQLITE_ERROR;
! 2718: }
! 2719: }
! 2720:
! 2721: while( pCur->iLvl>=0 ){
! 2722: FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
! 2723: struct dirent *pEntry = readdir(pLvl->pDir);
! 2724: if( pEntry ){
! 2725: if( pEntry->d_name[0]=='.' ){
! 2726: if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
! 2727: if( pEntry->d_name[1]=='\0' ) continue;
! 2728: }
! 2729: sqlite3_free(pCur->zPath);
! 2730: pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
! 2731: if( pCur->zPath==0 ) return SQLITE_NOMEM;
! 2732: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
! 2733: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
! 2734: return SQLITE_ERROR;
! 2735: }
! 2736: return SQLITE_OK;
! 2737: }
! 2738: closedir(pLvl->pDir);
! 2739: sqlite3_free(pLvl->zDir);
! 2740: pLvl->pDir = 0;
! 2741: pLvl->zDir = 0;
! 2742: pCur->iLvl--;
! 2743: }
! 2744:
! 2745: /* EOF */
! 2746: sqlite3_free(pCur->zPath);
! 2747: pCur->zPath = 0;
! 2748: return SQLITE_OK;
! 2749: }
! 2750:
! 2751: /*
! 2752: ** Return values of columns for the row at which the series_cursor
! 2753: ** is currently pointing.
! 2754: */
! 2755: static int fsdirColumn(
! 2756: sqlite3_vtab_cursor *cur, /* The cursor */
! 2757: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 2758: int i /* Which column to return */
! 2759: ){
! 2760: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2761: switch( i ){
! 2762: case FSDIR_COLUMN_NAME: {
! 2763: sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
! 2764: break;
! 2765: }
! 2766:
! 2767: case FSDIR_COLUMN_MODE:
! 2768: sqlite3_result_int64(ctx, pCur->sStat.st_mode);
! 2769: break;
! 2770:
! 2771: case FSDIR_COLUMN_MTIME:
! 2772: sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
! 2773: break;
! 2774:
! 2775: case FSDIR_COLUMN_DATA: {
! 2776: mode_t m = pCur->sStat.st_mode;
! 2777: if( S_ISDIR(m) ){
! 2778: sqlite3_result_null(ctx);
! 2779: #if !defined(_WIN32) && !defined(WIN32)
! 2780: }else if( S_ISLNK(m) ){
! 2781: char aStatic[64];
! 2782: char *aBuf = aStatic;
! 2783: sqlite3_int64 nBuf = 64;
! 2784: int n;
! 2785:
! 2786: while( 1 ){
! 2787: n = readlink(pCur->zPath, aBuf, nBuf);
! 2788: if( n<nBuf ) break;
! 2789: if( aBuf!=aStatic ) sqlite3_free(aBuf);
! 2790: nBuf = nBuf*2;
! 2791: aBuf = sqlite3_malloc64(nBuf);
! 2792: if( aBuf==0 ){
! 2793: sqlite3_result_error_nomem(ctx);
! 2794: return SQLITE_NOMEM;
! 2795: }
! 2796: }
! 2797:
! 2798: sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
! 2799: if( aBuf!=aStatic ) sqlite3_free(aBuf);
! 2800: #endif
! 2801: }else{
! 2802: readFileContents(ctx, pCur->zPath);
! 2803: }
! 2804: }
! 2805: case FSDIR_COLUMN_PATH:
! 2806: default: {
! 2807: /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
! 2808: ** always return their values as NULL */
! 2809: break;
! 2810: }
! 2811: }
! 2812: return SQLITE_OK;
! 2813: }
! 2814:
! 2815: /*
! 2816: ** Return the rowid for the current row. In this implementation, the
! 2817: ** first row returned is assigned rowid value 1, and each subsequent
! 2818: ** row a value 1 more than that of the previous.
! 2819: */
! 2820: static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 2821: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2822: *pRowid = pCur->iRowid;
! 2823: return SQLITE_OK;
! 2824: }
! 2825:
! 2826: /*
! 2827: ** Return TRUE if the cursor has been moved off of the last
! 2828: ** row of output.
! 2829: */
! 2830: static int fsdirEof(sqlite3_vtab_cursor *cur){
! 2831: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2832: return (pCur->zPath==0);
! 2833: }
! 2834:
! 2835: /*
! 2836: ** xFilter callback.
! 2837: **
! 2838: ** idxNum==1 PATH parameter only
! 2839: ** idxNum==2 Both PATH and DIR supplied
! 2840: */
! 2841: static int fsdirFilter(
! 2842: sqlite3_vtab_cursor *cur,
! 2843: int idxNum, const char *idxStr,
! 2844: int argc, sqlite3_value **argv
! 2845: ){
! 2846: const char *zDir = 0;
! 2847: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 2848: (void)idxStr;
! 2849: fsdirResetCursor(pCur);
! 2850:
! 2851: if( idxNum==0 ){
! 2852: fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
! 2853: return SQLITE_ERROR;
! 2854: }
! 2855:
! 2856: assert( argc==idxNum && (argc==1 || argc==2) );
! 2857: zDir = (const char*)sqlite3_value_text(argv[0]);
! 2858: if( zDir==0 ){
! 2859: fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
! 2860: return SQLITE_ERROR;
! 2861: }
! 2862: if( argc==2 ){
! 2863: pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
! 2864: }
! 2865: if( pCur->zBase ){
! 2866: pCur->nBase = (int)strlen(pCur->zBase)+1;
! 2867: pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
! 2868: }else{
! 2869: pCur->zPath = sqlite3_mprintf("%s", zDir);
! 2870: }
! 2871:
! 2872: if( pCur->zPath==0 ){
! 2873: return SQLITE_NOMEM;
! 2874: }
! 2875: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
! 2876: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
! 2877: return SQLITE_ERROR;
! 2878: }
! 2879:
! 2880: return SQLITE_OK;
! 2881: }
! 2882:
! 2883: /*
! 2884: ** SQLite will invoke this method one or more times while planning a query
! 2885: ** that uses the generate_series virtual table. This routine needs to create
! 2886: ** a query plan for each invocation and compute an estimated cost for that
! 2887: ** plan.
! 2888: **
! 2889: ** In this implementation idxNum is used to represent the
! 2890: ** query plan. idxStr is unused.
! 2891: **
! 2892: ** The query plan is represented by values of idxNum:
! 2893: **
! 2894: ** (1) The path value is supplied by argv[0]
! 2895: ** (2) Path is in argv[0] and dir is in argv[1]
! 2896: */
! 2897: static int fsdirBestIndex(
! 2898: sqlite3_vtab *tab,
! 2899: sqlite3_index_info *pIdxInfo
! 2900: ){
! 2901: int i; /* Loop over constraints */
! 2902: int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
! 2903: int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
! 2904: int seenPath = 0; /* True if an unusable PATH= constraint is seen */
! 2905: int seenDir = 0; /* True if an unusable DIR= constraint is seen */
! 2906: const struct sqlite3_index_constraint *pConstraint;
! 2907:
! 2908: (void)tab;
! 2909: pConstraint = pIdxInfo->aConstraint;
! 2910: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
! 2911: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
! 2912: switch( pConstraint->iColumn ){
! 2913: case FSDIR_COLUMN_PATH: {
! 2914: if( pConstraint->usable ){
! 2915: idxPath = i;
! 2916: seenPath = 0;
! 2917: }else if( idxPath<0 ){
! 2918: seenPath = 1;
! 2919: }
! 2920: break;
! 2921: }
! 2922: case FSDIR_COLUMN_DIR: {
! 2923: if( pConstraint->usable ){
! 2924: idxDir = i;
! 2925: seenDir = 0;
! 2926: }else if( idxDir<0 ){
! 2927: seenDir = 1;
! 2928: }
! 2929: break;
! 2930: }
! 2931: }
! 2932: }
! 2933: if( seenPath || seenDir ){
! 2934: /* If input parameters are unusable, disallow this plan */
! 2935: return SQLITE_CONSTRAINT;
! 2936: }
! 2937:
! 2938: if( idxPath<0 ){
! 2939: pIdxInfo->idxNum = 0;
! 2940: /* The pIdxInfo->estimatedCost should have been initialized to a huge
! 2941: ** number. Leave it unchanged. */
! 2942: pIdxInfo->estimatedRows = 0x7fffffff;
! 2943: }else{
! 2944: pIdxInfo->aConstraintUsage[idxPath].omit = 1;
! 2945: pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
! 2946: if( idxDir>=0 ){
! 2947: pIdxInfo->aConstraintUsage[idxDir].omit = 1;
! 2948: pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
! 2949: pIdxInfo->idxNum = 2;
! 2950: pIdxInfo->estimatedCost = 10.0;
! 2951: }else{
! 2952: pIdxInfo->idxNum = 1;
! 2953: pIdxInfo->estimatedCost = 100.0;
! 2954: }
! 2955: }
! 2956:
! 2957: return SQLITE_OK;
! 2958: }
! 2959:
! 2960: /*
! 2961: ** Register the "fsdir" virtual table.
! 2962: */
! 2963: static int fsdirRegister(sqlite3 *db){
! 2964: static sqlite3_module fsdirModule = {
! 2965: 0, /* iVersion */
! 2966: 0, /* xCreate */
! 2967: fsdirConnect, /* xConnect */
! 2968: fsdirBestIndex, /* xBestIndex */
! 2969: fsdirDisconnect, /* xDisconnect */
! 2970: 0, /* xDestroy */
! 2971: fsdirOpen, /* xOpen - open a cursor */
! 2972: fsdirClose, /* xClose - close a cursor */
! 2973: fsdirFilter, /* xFilter - configure scan constraints */
! 2974: fsdirNext, /* xNext - advance a cursor */
! 2975: fsdirEof, /* xEof - check for end of scan */
! 2976: fsdirColumn, /* xColumn - read data */
! 2977: fsdirRowid, /* xRowid - read data */
! 2978: 0, /* xUpdate */
! 2979: 0, /* xBegin */
! 2980: 0, /* xSync */
! 2981: 0, /* xCommit */
! 2982: 0, /* xRollback */
! 2983: 0, /* xFindMethod */
! 2984: 0, /* xRename */
! 2985: 0, /* xSavepoint */
! 2986: 0, /* xRelease */
! 2987: 0, /* xRollbackTo */
! 2988: 0, /* xShadowName */
! 2989: };
! 2990:
! 2991: int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
! 2992: return rc;
! 2993: }
! 2994: #else /* SQLITE_OMIT_VIRTUALTABLE */
! 2995: # define fsdirRegister(x) SQLITE_OK
! 2996: #endif
! 2997:
! 2998: #ifdef _WIN32
! 2999:
! 3000: #endif
! 3001: int sqlite3_fileio_init(
! 3002: sqlite3 *db,
! 3003: char **pzErrMsg,
! 3004: const sqlite3_api_routines *pApi
! 3005: ){
! 3006: int rc = SQLITE_OK;
! 3007: SQLITE_EXTENSION_INIT2(pApi);
! 3008: (void)pzErrMsg; /* Unused parameter */
! 3009: rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
! 3010: readfileFunc, 0, 0);
! 3011: if( rc==SQLITE_OK ){
! 3012: rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
! 3013: writefileFunc, 0, 0);
! 3014: }
! 3015: if( rc==SQLITE_OK ){
! 3016: rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
! 3017: lsModeFunc, 0, 0);
! 3018: }
! 3019: if( rc==SQLITE_OK ){
! 3020: rc = fsdirRegister(db);
! 3021: }
! 3022: return rc;
! 3023: }
! 3024:
! 3025: /************************* End ../ext/misc/fileio.c ********************/
! 3026: /************************* Begin ../ext/misc/completion.c ******************/
! 3027: /*
! 3028: ** 2017-07-10
! 3029: **
! 3030: ** The author disclaims copyright to this source code. In place of
! 3031: ** a legal notice, here is a blessing:
! 3032: **
! 3033: ** May you do good and not evil.
! 3034: ** May you find forgiveness for yourself and forgive others.
! 3035: ** May you share freely, never taking more than you give.
! 3036: **
! 3037: *************************************************************************
! 3038: **
! 3039: ** This file implements an eponymous virtual table that returns suggested
! 3040: ** completions for a partial SQL input.
! 3041: **
! 3042: ** Suggested usage:
! 3043: **
! 3044: ** SELECT DISTINCT candidate COLLATE nocase
! 3045: ** FROM completion($prefix,$wholeline)
! 3046: ** ORDER BY 1;
! 3047: **
! 3048: ** The two query parameters are optional. $prefix is the text of the
! 3049: ** current word being typed and that is to be completed. $wholeline is
! 3050: ** the complete input line, used for context.
! 3051: **
! 3052: ** The raw completion() table might return the same candidate multiple
! 3053: ** times, for example if the same column name is used to two or more
! 3054: ** tables. And the candidates are returned in an arbitrary order. Hence,
! 3055: ** the DISTINCT and ORDER BY are recommended.
! 3056: **
! 3057: ** This virtual table operates at the speed of human typing, and so there
! 3058: ** is no attempt to make it fast. Even a slow implementation will be much
! 3059: ** faster than any human can type.
! 3060: **
! 3061: */
! 3062: /* #include "sqlite3ext.h" */
! 3063: SQLITE_EXTENSION_INIT1
! 3064: #include <assert.h>
! 3065: #include <string.h>
! 3066: #include <ctype.h>
! 3067:
! 3068: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 3069:
! 3070: /* completion_vtab is a subclass of sqlite3_vtab which will
! 3071: ** serve as the underlying representation of a completion virtual table
! 3072: */
! 3073: typedef struct completion_vtab completion_vtab;
! 3074: struct completion_vtab {
! 3075: sqlite3_vtab base; /* Base class - must be first */
! 3076: sqlite3 *db; /* Database connection for this completion vtab */
! 3077: };
! 3078:
! 3079: /* completion_cursor is a subclass of sqlite3_vtab_cursor which will
! 3080: ** serve as the underlying representation of a cursor that scans
! 3081: ** over rows of the result
! 3082: */
! 3083: typedef struct completion_cursor completion_cursor;
! 3084: struct completion_cursor {
! 3085: sqlite3_vtab_cursor base; /* Base class - must be first */
! 3086: sqlite3 *db; /* Database connection for this cursor */
! 3087: int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
! 3088: char *zPrefix; /* The prefix for the word we want to complete */
! 3089: char *zLine; /* The whole that we want to complete */
! 3090: const char *zCurrentRow; /* Current output row */
! 3091: int szRow; /* Length of the zCurrentRow string */
! 3092: sqlite3_stmt *pStmt; /* Current statement */
! 3093: sqlite3_int64 iRowid; /* The rowid */
! 3094: int ePhase; /* Current phase */
! 3095: int j; /* inter-phase counter */
! 3096: };
! 3097:
! 3098: /* Values for ePhase:
! 3099: */
! 3100: #define COMPLETION_FIRST_PHASE 1
! 3101: #define COMPLETION_KEYWORDS 1
! 3102: #define COMPLETION_PRAGMAS 2
! 3103: #define COMPLETION_FUNCTIONS 3
! 3104: #define COMPLETION_COLLATIONS 4
! 3105: #define COMPLETION_INDEXES 5
! 3106: #define COMPLETION_TRIGGERS 6
! 3107: #define COMPLETION_DATABASES 7
! 3108: #define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
! 3109: #define COMPLETION_COLUMNS 9
! 3110: #define COMPLETION_MODULES 10
! 3111: #define COMPLETION_EOF 11
! 3112:
! 3113: /*
! 3114: ** The completionConnect() method is invoked to create a new
! 3115: ** completion_vtab that describes the completion virtual table.
! 3116: **
! 3117: ** Think of this routine as the constructor for completion_vtab objects.
! 3118: **
! 3119: ** All this routine needs to do is:
! 3120: **
! 3121: ** (1) Allocate the completion_vtab object and initialize all fields.
! 3122: **
! 3123: ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
! 3124: ** result set of queries against completion will look like.
! 3125: */
! 3126: static int completionConnect(
! 3127: sqlite3 *db,
! 3128: void *pAux,
! 3129: int argc, const char *const*argv,
! 3130: sqlite3_vtab **ppVtab,
! 3131: char **pzErr
! 3132: ){
! 3133: completion_vtab *pNew;
! 3134: int rc;
! 3135:
! 3136: (void)(pAux); /* Unused parameter */
! 3137: (void)(argc); /* Unused parameter */
! 3138: (void)(argv); /* Unused parameter */
! 3139: (void)(pzErr); /* Unused parameter */
! 3140:
! 3141: /* Column numbers */
! 3142: #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
! 3143: #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
! 3144: #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
! 3145: #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
! 3146:
! 3147: rc = sqlite3_declare_vtab(db,
! 3148: "CREATE TABLE x("
! 3149: " candidate TEXT,"
! 3150: " prefix TEXT HIDDEN,"
! 3151: " wholeline TEXT HIDDEN,"
! 3152: " phase INT HIDDEN" /* Used for debugging only */
! 3153: ")");
! 3154: if( rc==SQLITE_OK ){
! 3155: pNew = sqlite3_malloc( sizeof(*pNew) );
! 3156: *ppVtab = (sqlite3_vtab*)pNew;
! 3157: if( pNew==0 ) return SQLITE_NOMEM;
! 3158: memset(pNew, 0, sizeof(*pNew));
! 3159: pNew->db = db;
! 3160: }
! 3161: return rc;
! 3162: }
! 3163:
! 3164: /*
! 3165: ** This method is the destructor for completion_cursor objects.
! 3166: */
! 3167: static int completionDisconnect(sqlite3_vtab *pVtab){
! 3168: sqlite3_free(pVtab);
! 3169: return SQLITE_OK;
! 3170: }
! 3171:
! 3172: /*
! 3173: ** Constructor for a new completion_cursor object.
! 3174: */
! 3175: static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
! 3176: completion_cursor *pCur;
! 3177: pCur = sqlite3_malloc( sizeof(*pCur) );
! 3178: if( pCur==0 ) return SQLITE_NOMEM;
! 3179: memset(pCur, 0, sizeof(*pCur));
! 3180: pCur->db = ((completion_vtab*)p)->db;
! 3181: *ppCursor = &pCur->base;
! 3182: return SQLITE_OK;
! 3183: }
! 3184:
! 3185: /*
! 3186: ** Reset the completion_cursor.
! 3187: */
! 3188: static void completionCursorReset(completion_cursor *pCur){
! 3189: sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
! 3190: sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
! 3191: sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
! 3192: pCur->j = 0;
! 3193: }
! 3194:
! 3195: /*
! 3196: ** Destructor for a completion_cursor.
! 3197: */
! 3198: static int completionClose(sqlite3_vtab_cursor *cur){
! 3199: completionCursorReset((completion_cursor*)cur);
! 3200: sqlite3_free(cur);
! 3201: return SQLITE_OK;
! 3202: }
! 3203:
! 3204: /*
! 3205: ** Advance a completion_cursor to its next row of output.
! 3206: **
! 3207: ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
! 3208: ** record the current state of the scan. This routine sets ->zCurrentRow
! 3209: ** to the current row of output and then returns. If no more rows remain,
! 3210: ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
! 3211: ** table that has reached the end of its scan.
! 3212: **
! 3213: ** The current implementation just lists potential identifiers and
! 3214: ** keywords and filters them by zPrefix. Future enhancements should
! 3215: ** take zLine into account to try to restrict the set of identifiers and
! 3216: ** keywords based on what would be legal at the current point of input.
! 3217: */
! 3218: static int completionNext(sqlite3_vtab_cursor *cur){
! 3219: completion_cursor *pCur = (completion_cursor*)cur;
! 3220: int eNextPhase = 0; /* Next phase to try if current phase reaches end */
! 3221: int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
! 3222: pCur->iRowid++;
! 3223: while( pCur->ePhase!=COMPLETION_EOF ){
! 3224: switch( pCur->ePhase ){
! 3225: case COMPLETION_KEYWORDS: {
! 3226: if( pCur->j >= sqlite3_keyword_count() ){
! 3227: pCur->zCurrentRow = 0;
! 3228: pCur->ePhase = COMPLETION_DATABASES;
! 3229: }else{
! 3230: sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
! 3231: }
! 3232: iCol = -1;
! 3233: break;
! 3234: }
! 3235: case COMPLETION_DATABASES: {
! 3236: if( pCur->pStmt==0 ){
! 3237: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
! 3238: &pCur->pStmt, 0);
! 3239: }
! 3240: iCol = 1;
! 3241: eNextPhase = COMPLETION_TABLES;
! 3242: break;
! 3243: }
! 3244: case COMPLETION_TABLES: {
! 3245: if( pCur->pStmt==0 ){
! 3246: sqlite3_stmt *pS2;
! 3247: char *zSql = 0;
! 3248: const char *zSep = "";
! 3249: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
! 3250: while( sqlite3_step(pS2)==SQLITE_ROW ){
! 3251: const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
! 3252: zSql = sqlite3_mprintf(
! 3253: "%z%s"
! 3254: "SELECT name FROM \"%w\".sqlite_master",
! 3255: zSql, zSep, zDb
! 3256: );
! 3257: if( zSql==0 ) return SQLITE_NOMEM;
! 3258: zSep = " UNION ";
! 3259: }
! 3260: sqlite3_finalize(pS2);
! 3261: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
! 3262: sqlite3_free(zSql);
! 3263: }
! 3264: iCol = 0;
! 3265: eNextPhase = COMPLETION_COLUMNS;
! 3266: break;
! 3267: }
! 3268: case COMPLETION_COLUMNS: {
! 3269: if( pCur->pStmt==0 ){
! 3270: sqlite3_stmt *pS2;
! 3271: char *zSql = 0;
! 3272: const char *zSep = "";
! 3273: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
! 3274: while( sqlite3_step(pS2)==SQLITE_ROW ){
! 3275: const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
! 3276: zSql = sqlite3_mprintf(
! 3277: "%z%s"
! 3278: "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
! 3279: " JOIN pragma_table_info(sm.name,%Q) AS pti"
! 3280: " WHERE sm.type='table'",
! 3281: zSql, zSep, zDb, zDb
! 3282: );
! 3283: if( zSql==0 ) return SQLITE_NOMEM;
! 3284: zSep = " UNION ";
! 3285: }
! 3286: sqlite3_finalize(pS2);
! 3287: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
! 3288: sqlite3_free(zSql);
! 3289: }
! 3290: iCol = 0;
! 3291: eNextPhase = COMPLETION_EOF;
! 3292: break;
! 3293: }
! 3294: }
! 3295: if( iCol<0 ){
! 3296: /* This case is when the phase presets zCurrentRow */
! 3297: if( pCur->zCurrentRow==0 ) continue;
! 3298: }else{
! 3299: if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
! 3300: /* Extract the next row of content */
! 3301: pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
! 3302: pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
! 3303: }else{
! 3304: /* When all rows are finished, advance to the next phase */
! 3305: sqlite3_finalize(pCur->pStmt);
! 3306: pCur->pStmt = 0;
! 3307: pCur->ePhase = eNextPhase;
! 3308: continue;
! 3309: }
! 3310: }
! 3311: if( pCur->nPrefix==0 ) break;
! 3312: if( pCur->nPrefix<=pCur->szRow
! 3313: && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
! 3314: ){
! 3315: break;
! 3316: }
! 3317: }
! 3318:
! 3319: return SQLITE_OK;
! 3320: }
! 3321:
! 3322: /*
! 3323: ** Return values of columns for the row at which the completion_cursor
! 3324: ** is currently pointing.
! 3325: */
! 3326: static int completionColumn(
! 3327: sqlite3_vtab_cursor *cur, /* The cursor */
! 3328: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 3329: int i /* Which column to return */
! 3330: ){
! 3331: completion_cursor *pCur = (completion_cursor*)cur;
! 3332: switch( i ){
! 3333: case COMPLETION_COLUMN_CANDIDATE: {
! 3334: sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
! 3335: break;
! 3336: }
! 3337: case COMPLETION_COLUMN_PREFIX: {
! 3338: sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
! 3339: break;
! 3340: }
! 3341: case COMPLETION_COLUMN_WHOLELINE: {
! 3342: sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
! 3343: break;
! 3344: }
! 3345: case COMPLETION_COLUMN_PHASE: {
! 3346: sqlite3_result_int(ctx, pCur->ePhase);
! 3347: break;
! 3348: }
! 3349: }
! 3350: return SQLITE_OK;
! 3351: }
! 3352:
! 3353: /*
! 3354: ** Return the rowid for the current row. In this implementation, the
! 3355: ** rowid is the same as the output value.
! 3356: */
! 3357: static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 3358: completion_cursor *pCur = (completion_cursor*)cur;
! 3359: *pRowid = pCur->iRowid;
! 3360: return SQLITE_OK;
! 3361: }
! 3362:
! 3363: /*
! 3364: ** Return TRUE if the cursor has been moved off of the last
! 3365: ** row of output.
! 3366: */
! 3367: static int completionEof(sqlite3_vtab_cursor *cur){
! 3368: completion_cursor *pCur = (completion_cursor*)cur;
! 3369: return pCur->ePhase >= COMPLETION_EOF;
! 3370: }
! 3371:
! 3372: /*
! 3373: ** This method is called to "rewind" the completion_cursor object back
! 3374: ** to the first row of output. This method is always called at least
! 3375: ** once prior to any call to completionColumn() or completionRowid() or
! 3376: ** completionEof().
! 3377: */
! 3378: static int completionFilter(
! 3379: sqlite3_vtab_cursor *pVtabCursor,
! 3380: int idxNum, const char *idxStr,
! 3381: int argc, sqlite3_value **argv
! 3382: ){
! 3383: completion_cursor *pCur = (completion_cursor *)pVtabCursor;
! 3384: int iArg = 0;
! 3385: (void)(idxStr); /* Unused parameter */
! 3386: (void)(argc); /* Unused parameter */
! 3387: completionCursorReset(pCur);
! 3388: if( idxNum & 1 ){
! 3389: pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
! 3390: if( pCur->nPrefix>0 ){
! 3391: pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
! 3392: if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
! 3393: }
! 3394: iArg = 1;
! 3395: }
! 3396: if( idxNum & 2 ){
! 3397: pCur->nLine = sqlite3_value_bytes(argv[iArg]);
! 3398: if( pCur->nLine>0 ){
! 3399: pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
! 3400: if( pCur->zLine==0 ) return SQLITE_NOMEM;
! 3401: }
! 3402: }
! 3403: if( pCur->zLine!=0 && pCur->zPrefix==0 ){
! 3404: int i = pCur->nLine;
! 3405: while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
! 3406: i--;
! 3407: }
! 3408: pCur->nPrefix = pCur->nLine - i;
! 3409: if( pCur->nPrefix>0 ){
! 3410: pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
! 3411: if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
! 3412: }
! 3413: }
! 3414: pCur->iRowid = 0;
! 3415: pCur->ePhase = COMPLETION_FIRST_PHASE;
! 3416: return completionNext(pVtabCursor);
! 3417: }
! 3418:
! 3419: /*
! 3420: ** SQLite will invoke this method one or more times while planning a query
! 3421: ** that uses the completion virtual table. This routine needs to create
! 3422: ** a query plan for each invocation and compute an estimated cost for that
! 3423: ** plan.
! 3424: **
! 3425: ** There are two hidden parameters that act as arguments to the table-valued
! 3426: ** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
! 3427: ** is available and bit 1 is set if "wholeline" is available.
! 3428: */
! 3429: static int completionBestIndex(
! 3430: sqlite3_vtab *tab,
! 3431: sqlite3_index_info *pIdxInfo
! 3432: ){
! 3433: int i; /* Loop over constraints */
! 3434: int idxNum = 0; /* The query plan bitmask */
! 3435: int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
! 3436: int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
! 3437: int nArg = 0; /* Number of arguments that completeFilter() expects */
! 3438: const struct sqlite3_index_constraint *pConstraint;
! 3439:
! 3440: (void)(tab); /* Unused parameter */
! 3441: pConstraint = pIdxInfo->aConstraint;
! 3442: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
! 3443: if( pConstraint->usable==0 ) continue;
! 3444: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
! 3445: switch( pConstraint->iColumn ){
! 3446: case COMPLETION_COLUMN_PREFIX:
! 3447: prefixIdx = i;
! 3448: idxNum |= 1;
! 3449: break;
! 3450: case COMPLETION_COLUMN_WHOLELINE:
! 3451: wholelineIdx = i;
! 3452: idxNum |= 2;
! 3453: break;
! 3454: }
! 3455: }
! 3456: if( prefixIdx>=0 ){
! 3457: pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
! 3458: pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
! 3459: }
! 3460: if( wholelineIdx>=0 ){
! 3461: pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
! 3462: pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
! 3463: }
! 3464: pIdxInfo->idxNum = idxNum;
! 3465: pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
! 3466: pIdxInfo->estimatedRows = 500 - 100*nArg;
! 3467: return SQLITE_OK;
! 3468: }
! 3469:
! 3470: /*
! 3471: ** This following structure defines all the methods for the
! 3472: ** completion virtual table.
! 3473: */
! 3474: static sqlite3_module completionModule = {
! 3475: 0, /* iVersion */
! 3476: 0, /* xCreate */
! 3477: completionConnect, /* xConnect */
! 3478: completionBestIndex, /* xBestIndex */
! 3479: completionDisconnect, /* xDisconnect */
! 3480: 0, /* xDestroy */
! 3481: completionOpen, /* xOpen - open a cursor */
! 3482: completionClose, /* xClose - close a cursor */
! 3483: completionFilter, /* xFilter - configure scan constraints */
! 3484: completionNext, /* xNext - advance a cursor */
! 3485: completionEof, /* xEof - check for end of scan */
! 3486: completionColumn, /* xColumn - read data */
! 3487: completionRowid, /* xRowid - read data */
! 3488: 0, /* xUpdate */
! 3489: 0, /* xBegin */
! 3490: 0, /* xSync */
! 3491: 0, /* xCommit */
! 3492: 0, /* xRollback */
! 3493: 0, /* xFindMethod */
! 3494: 0, /* xRename */
! 3495: 0, /* xSavepoint */
! 3496: 0, /* xRelease */
! 3497: 0, /* xRollbackTo */
! 3498: 0 /* xShadowName */
! 3499: };
! 3500:
! 3501: #endif /* SQLITE_OMIT_VIRTUALTABLE */
! 3502:
! 3503: int sqlite3CompletionVtabInit(sqlite3 *db){
! 3504: int rc = SQLITE_OK;
! 3505: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 3506: rc = sqlite3_create_module(db, "completion", &completionModule, 0);
! 3507: #endif
! 3508: return rc;
! 3509: }
! 3510:
! 3511: #ifdef _WIN32
! 3512:
! 3513: #endif
! 3514: int sqlite3_completion_init(
! 3515: sqlite3 *db,
! 3516: char **pzErrMsg,
! 3517: const sqlite3_api_routines *pApi
! 3518: ){
! 3519: int rc = SQLITE_OK;
! 3520: SQLITE_EXTENSION_INIT2(pApi);
! 3521: (void)(pzErrMsg); /* Unused parameter */
! 3522: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 3523: rc = sqlite3CompletionVtabInit(db);
! 3524: #endif
! 3525: return rc;
! 3526: }
! 3527:
! 3528: /************************* End ../ext/misc/completion.c ********************/
! 3529: /************************* Begin ../ext/misc/appendvfs.c ******************/
! 3530: /*
! 3531: ** 2017-10-20
! 3532: **
! 3533: ** The author disclaims copyright to this source code. In place of
! 3534: ** a legal notice, here is a blessing:
! 3535: **
! 3536: ** May you do good and not evil.
! 3537: ** May you find forgiveness for yourself and forgive others.
! 3538: ** May you share freely, never taking more than you give.
! 3539: **
! 3540: ******************************************************************************
! 3541: **
! 3542: ** This file implements a VFS shim that allows an SQLite database to be
! 3543: ** appended onto the end of some other file, such as an executable.
! 3544: **
! 3545: ** A special record must appear at the end of the file that identifies the
! 3546: ** file as an appended database and provides an offset to page 1. For
! 3547: ** best performance page 1 should be located at a disk page boundary, though
! 3548: ** that is not required.
! 3549: **
! 3550: ** When opening a database using this VFS, the connection might treat
! 3551: ** the file as an ordinary SQLite database, or it might treat is as a
! 3552: ** database appended onto some other file. Here are the rules:
! 3553: **
! 3554: ** (1) When opening a new empty file, that file is treated as an ordinary
! 3555: ** database.
! 3556: **
! 3557: ** (2) When opening a file that begins with the standard SQLite prefix
! 3558: ** string "SQLite format 3", that file is treated as an ordinary
! 3559: ** database.
! 3560: **
! 3561: ** (3) When opening a file that ends with the appendvfs trailer string
! 3562: ** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
! 3563: ** database.
! 3564: **
! 3565: ** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
! 3566: ** set, then a new database is appended to the already existing file.
! 3567: **
! 3568: ** (5) Otherwise, SQLITE_CANTOPEN is returned.
! 3569: **
! 3570: ** To avoid unnecessary complications with the PENDING_BYTE, the size of
! 3571: ** the file containing the database is limited to 1GB. This VFS will refuse
! 3572: ** to read or write past the 1GB mark. This restriction might be lifted in
! 3573: ** future versions. For now, if you need a large database, then keep the
! 3574: ** database in a separate file.
! 3575: **
! 3576: ** If the file being opened is not an appended database, then this shim is
! 3577: ** a pass-through into the default underlying VFS.
! 3578: **/
! 3579: /* #include "sqlite3ext.h" */
! 3580: SQLITE_EXTENSION_INIT1
! 3581: #include <string.h>
! 3582: #include <assert.h>
! 3583:
! 3584: /* The append mark at the end of the database is:
! 3585: **
! 3586: ** Start-Of-SQLite3-NNNNNNNN
! 3587: ** 123456789 123456789 12345
! 3588: **
! 3589: ** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
! 3590: ** the offset to page 1.
! 3591: */
! 3592: #define APND_MARK_PREFIX "Start-Of-SQLite3-"
! 3593: #define APND_MARK_PREFIX_SZ 17
! 3594: #define APND_MARK_SIZE 25
! 3595:
! 3596: /*
! 3597: ** Maximum size of the combined prefix + database + append-mark. This
! 3598: ** must be less than 0x40000000 to avoid locking issues on Windows.
! 3599: */
! 3600: #define APND_MAX_SIZE (65536*15259)
! 3601:
! 3602: /*
! 3603: ** Forward declaration of objects used by this utility
! 3604: */
! 3605: typedef struct sqlite3_vfs ApndVfs;
! 3606: typedef struct ApndFile ApndFile;
! 3607:
! 3608: /* Access to a lower-level VFS that (might) implement dynamic loading,
! 3609: ** access to randomness, etc.
! 3610: */
! 3611: #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
! 3612: #define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
! 3613:
! 3614: /* An open file */
! 3615: struct ApndFile {
! 3616: sqlite3_file base; /* IO methods */
! 3617: sqlite3_int64 iPgOne; /* File offset to page 1 */
! 3618: sqlite3_int64 iMark; /* Start of the append-mark */
! 3619: };
! 3620:
! 3621: /*
! 3622: ** Methods for ApndFile
! 3623: */
! 3624: static int apndClose(sqlite3_file*);
! 3625: static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
! 3626: static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
! 3627: static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
! 3628: static int apndSync(sqlite3_file*, int flags);
! 3629: static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
! 3630: static int apndLock(sqlite3_file*, int);
! 3631: static int apndUnlock(sqlite3_file*, int);
! 3632: static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
! 3633: static int apndFileControl(sqlite3_file*, int op, void *pArg);
! 3634: static int apndSectorSize(sqlite3_file*);
! 3635: static int apndDeviceCharacteristics(sqlite3_file*);
! 3636: static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
! 3637: static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
! 3638: static void apndShmBarrier(sqlite3_file*);
! 3639: static int apndShmUnmap(sqlite3_file*, int deleteFlag);
! 3640: static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
! 3641: static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
! 3642:
! 3643: /*
! 3644: ** Methods for ApndVfs
! 3645: */
! 3646: static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
! 3647: static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
! 3648: static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
! 3649: static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
! 3650: static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
! 3651: static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
! 3652: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
! 3653: static void apndDlClose(sqlite3_vfs*, void*);
! 3654: static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
! 3655: static int apndSleep(sqlite3_vfs*, int microseconds);
! 3656: static int apndCurrentTime(sqlite3_vfs*, double*);
! 3657: static int apndGetLastError(sqlite3_vfs*, int, char *);
! 3658: static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
! 3659: static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
! 3660: static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
! 3661: static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
! 3662:
! 3663: static sqlite3_vfs apnd_vfs = {
! 3664: 3, /* iVersion (set when registered) */
! 3665: 0, /* szOsFile (set when registered) */
! 3666: 1024, /* mxPathname */
! 3667: 0, /* pNext */
! 3668: "apndvfs", /* zName */
! 3669: 0, /* pAppData (set when registered) */
! 3670: apndOpen, /* xOpen */
! 3671: apndDelete, /* xDelete */
! 3672: apndAccess, /* xAccess */
! 3673: apndFullPathname, /* xFullPathname */
! 3674: apndDlOpen, /* xDlOpen */
! 3675: apndDlError, /* xDlError */
! 3676: apndDlSym, /* xDlSym */
! 3677: apndDlClose, /* xDlClose */
! 3678: apndRandomness, /* xRandomness */
! 3679: apndSleep, /* xSleep */
! 3680: apndCurrentTime, /* xCurrentTime */
! 3681: apndGetLastError, /* xGetLastError */
! 3682: apndCurrentTimeInt64, /* xCurrentTimeInt64 */
! 3683: apndSetSystemCall, /* xSetSystemCall */
! 3684: apndGetSystemCall, /* xGetSystemCall */
! 3685: apndNextSystemCall /* xNextSystemCall */
! 3686: };
! 3687:
! 3688: static const sqlite3_io_methods apnd_io_methods = {
! 3689: 3, /* iVersion */
! 3690: apndClose, /* xClose */
! 3691: apndRead, /* xRead */
! 3692: apndWrite, /* xWrite */
! 3693: apndTruncate, /* xTruncate */
! 3694: apndSync, /* xSync */
! 3695: apndFileSize, /* xFileSize */
! 3696: apndLock, /* xLock */
! 3697: apndUnlock, /* xUnlock */
! 3698: apndCheckReservedLock, /* xCheckReservedLock */
! 3699: apndFileControl, /* xFileControl */
! 3700: apndSectorSize, /* xSectorSize */
! 3701: apndDeviceCharacteristics, /* xDeviceCharacteristics */
! 3702: apndShmMap, /* xShmMap */
! 3703: apndShmLock, /* xShmLock */
! 3704: apndShmBarrier, /* xShmBarrier */
! 3705: apndShmUnmap, /* xShmUnmap */
! 3706: apndFetch, /* xFetch */
! 3707: apndUnfetch /* xUnfetch */
! 3708: };
! 3709:
! 3710:
! 3711:
! 3712: /*
! 3713: ** Close an apnd-file.
! 3714: */
! 3715: static int apndClose(sqlite3_file *pFile){
! 3716: pFile = ORIGFILE(pFile);
! 3717: return pFile->pMethods->xClose(pFile);
! 3718: }
! 3719:
! 3720: /*
! 3721: ** Read data from an apnd-file.
! 3722: */
! 3723: static int apndRead(
! 3724: sqlite3_file *pFile,
! 3725: void *zBuf,
! 3726: int iAmt,
! 3727: sqlite_int64 iOfst
! 3728: ){
! 3729: ApndFile *p = (ApndFile *)pFile;
! 3730: pFile = ORIGFILE(pFile);
! 3731: return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
! 3732: }
! 3733:
! 3734: /*
! 3735: ** Add the append-mark onto the end of the file.
! 3736: */
! 3737: static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
! 3738: int i;
! 3739: unsigned char a[APND_MARK_SIZE];
! 3740: memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
! 3741: for(i=0; i<8; i++){
! 3742: a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
! 3743: }
! 3744: return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
! 3745: }
! 3746:
! 3747: /*
! 3748: ** Write data to an apnd-file.
! 3749: */
! 3750: static int apndWrite(
! 3751: sqlite3_file *pFile,
! 3752: const void *zBuf,
! 3753: int iAmt,
! 3754: sqlite_int64 iOfst
! 3755: ){
! 3756: int rc;
! 3757: ApndFile *p = (ApndFile *)pFile;
! 3758: pFile = ORIGFILE(pFile);
! 3759: if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
! 3760: rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
! 3761: if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
! 3762: sqlite3_int64 sz = 0;
! 3763: rc = pFile->pMethods->xFileSize(pFile, &sz);
! 3764: if( rc==SQLITE_OK ){
! 3765: p->iMark = sz - APND_MARK_SIZE;
! 3766: if( iOfst + iAmt + p->iPgOne > p->iMark ){
! 3767: p->iMark = p->iPgOne + iOfst + iAmt;
! 3768: rc = apndWriteMark(p, pFile);
! 3769: }
! 3770: }
! 3771: }
! 3772: return rc;
! 3773: }
! 3774:
! 3775: /*
! 3776: ** Truncate an apnd-file.
! 3777: */
! 3778: static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
! 3779: int rc;
! 3780: ApndFile *p = (ApndFile *)pFile;
! 3781: pFile = ORIGFILE(pFile);
! 3782: rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
! 3783: if( rc==SQLITE_OK ){
! 3784: p->iMark = p->iPgOne+size;
! 3785: rc = apndWriteMark(p, pFile);
! 3786: }
! 3787: return rc;
! 3788: }
! 3789:
! 3790: /*
! 3791: ** Sync an apnd-file.
! 3792: */
! 3793: static int apndSync(sqlite3_file *pFile, int flags){
! 3794: pFile = ORIGFILE(pFile);
! 3795: return pFile->pMethods->xSync(pFile, flags);
! 3796: }
! 3797:
! 3798: /*
! 3799: ** Return the current file-size of an apnd-file.
! 3800: */
! 3801: static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
! 3802: ApndFile *p = (ApndFile *)pFile;
! 3803: int rc;
! 3804: pFile = ORIGFILE(p);
! 3805: rc = pFile->pMethods->xFileSize(pFile, pSize);
! 3806: if( rc==SQLITE_OK && p->iPgOne ){
! 3807: *pSize -= p->iPgOne + APND_MARK_SIZE;
! 3808: }
! 3809: return rc;
! 3810: }
! 3811:
! 3812: /*
! 3813: ** Lock an apnd-file.
! 3814: */
! 3815: static int apndLock(sqlite3_file *pFile, int eLock){
! 3816: pFile = ORIGFILE(pFile);
! 3817: return pFile->pMethods->xLock(pFile, eLock);
! 3818: }
! 3819:
! 3820: /*
! 3821: ** Unlock an apnd-file.
! 3822: */
! 3823: static int apndUnlock(sqlite3_file *pFile, int eLock){
! 3824: pFile = ORIGFILE(pFile);
! 3825: return pFile->pMethods->xUnlock(pFile, eLock);
! 3826: }
! 3827:
! 3828: /*
! 3829: ** Check if another file-handle holds a RESERVED lock on an apnd-file.
! 3830: */
! 3831: static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
! 3832: pFile = ORIGFILE(pFile);
! 3833: return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
! 3834: }
! 3835:
! 3836: /*
! 3837: ** File control method. For custom operations on an apnd-file.
! 3838: */
! 3839: static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
! 3840: ApndFile *p = (ApndFile *)pFile;
! 3841: int rc;
! 3842: pFile = ORIGFILE(pFile);
! 3843: rc = pFile->pMethods->xFileControl(pFile, op, pArg);
! 3844: if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
! 3845: *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
! 3846: }
! 3847: return rc;
! 3848: }
! 3849:
! 3850: /*
! 3851: ** Return the sector-size in bytes for an apnd-file.
! 3852: */
! 3853: static int apndSectorSize(sqlite3_file *pFile){
! 3854: pFile = ORIGFILE(pFile);
! 3855: return pFile->pMethods->xSectorSize(pFile);
! 3856: }
! 3857:
! 3858: /*
! 3859: ** Return the device characteristic flags supported by an apnd-file.
! 3860: */
! 3861: static int apndDeviceCharacteristics(sqlite3_file *pFile){
! 3862: pFile = ORIGFILE(pFile);
! 3863: return pFile->pMethods->xDeviceCharacteristics(pFile);
! 3864: }
! 3865:
! 3866: /* Create a shared memory file mapping */
! 3867: static int apndShmMap(
! 3868: sqlite3_file *pFile,
! 3869: int iPg,
! 3870: int pgsz,
! 3871: int bExtend,
! 3872: void volatile **pp
! 3873: ){
! 3874: pFile = ORIGFILE(pFile);
! 3875: return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
! 3876: }
! 3877:
! 3878: /* Perform locking on a shared-memory segment */
! 3879: static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
! 3880: pFile = ORIGFILE(pFile);
! 3881: return pFile->pMethods->xShmLock(pFile,offset,n,flags);
! 3882: }
! 3883:
! 3884: /* Memory barrier operation on shared memory */
! 3885: static void apndShmBarrier(sqlite3_file *pFile){
! 3886: pFile = ORIGFILE(pFile);
! 3887: pFile->pMethods->xShmBarrier(pFile);
! 3888: }
! 3889:
! 3890: /* Unmap a shared memory segment */
! 3891: static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
! 3892: pFile = ORIGFILE(pFile);
! 3893: return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
! 3894: }
! 3895:
! 3896: /* Fetch a page of a memory-mapped file */
! 3897: static int apndFetch(
! 3898: sqlite3_file *pFile,
! 3899: sqlite3_int64 iOfst,
! 3900: int iAmt,
! 3901: void **pp
! 3902: ){
! 3903: ApndFile *p = (ApndFile *)pFile;
! 3904: pFile = ORIGFILE(pFile);
! 3905: return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
! 3906: }
! 3907:
! 3908: /* Release a memory-mapped page */
! 3909: static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
! 3910: ApndFile *p = (ApndFile *)pFile;
! 3911: pFile = ORIGFILE(pFile);
! 3912: return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
! 3913: }
! 3914:
! 3915: /*
! 3916: ** Check to see if the file is an ordinary SQLite database file.
! 3917: */
! 3918: static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
! 3919: int rc;
! 3920: char zHdr[16];
! 3921: static const char aSqliteHdr[] = "SQLite format 3";
! 3922: if( sz<512 ) return 0;
! 3923: rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
! 3924: if( rc ) return 0;
! 3925: return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
! 3926: }
! 3927:
! 3928: /*
! 3929: ** Try to read the append-mark off the end of a file. Return the
! 3930: ** start of the appended database if the append-mark is present. If
! 3931: ** there is no append-mark, return -1;
! 3932: */
! 3933: static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
! 3934: int rc, i;
! 3935: sqlite3_int64 iMark;
! 3936: unsigned char a[APND_MARK_SIZE];
! 3937:
! 3938: if( sz<=APND_MARK_SIZE ) return -1;
! 3939: rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
! 3940: if( rc ) return -1;
! 3941: if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
! 3942: iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
! 3943: for(i=1; i<8; i++){
! 3944: iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
! 3945: }
! 3946: return iMark;
! 3947: }
! 3948:
! 3949: /*
! 3950: ** Open an apnd file handle.
! 3951: */
! 3952: static int apndOpen(
! 3953: sqlite3_vfs *pVfs,
! 3954: const char *zName,
! 3955: sqlite3_file *pFile,
! 3956: int flags,
! 3957: int *pOutFlags
! 3958: ){
! 3959: ApndFile *p;
! 3960: sqlite3_file *pSubFile;
! 3961: sqlite3_vfs *pSubVfs;
! 3962: int rc;
! 3963: sqlite3_int64 sz;
! 3964: pSubVfs = ORIGVFS(pVfs);
! 3965: if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
! 3966: return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
! 3967: }
! 3968: p = (ApndFile*)pFile;
! 3969: memset(p, 0, sizeof(*p));
! 3970: pSubFile = ORIGFILE(pFile);
! 3971: p->base.pMethods = &apnd_io_methods;
! 3972: rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
! 3973: if( rc ) goto apnd_open_done;
! 3974: rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
! 3975: if( rc ){
! 3976: pSubFile->pMethods->xClose(pSubFile);
! 3977: goto apnd_open_done;
! 3978: }
! 3979: if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
! 3980: memmove(pFile, pSubFile, pSubVfs->szOsFile);
! 3981: return SQLITE_OK;
! 3982: }
! 3983: p->iMark = 0;
! 3984: p->iPgOne = apndReadMark(sz, pFile);
! 3985: if( p->iPgOne>0 ){
! 3986: return SQLITE_OK;
! 3987: }
! 3988: if( (flags & SQLITE_OPEN_CREATE)==0 ){
! 3989: pSubFile->pMethods->xClose(pSubFile);
! 3990: rc = SQLITE_CANTOPEN;
! 3991: }
! 3992: p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
! 3993: apnd_open_done:
! 3994: if( rc ) pFile->pMethods = 0;
! 3995: return rc;
! 3996: }
! 3997:
! 3998: /*
! 3999: ** All other VFS methods are pass-thrus.
! 4000: */
! 4001: static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
! 4002: return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
! 4003: }
! 4004: static int apndAccess(
! 4005: sqlite3_vfs *pVfs,
! 4006: const char *zPath,
! 4007: int flags,
! 4008: int *pResOut
! 4009: ){
! 4010: return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
! 4011: }
! 4012: static int apndFullPathname(
! 4013: sqlite3_vfs *pVfs,
! 4014: const char *zPath,
! 4015: int nOut,
! 4016: char *zOut
! 4017: ){
! 4018: return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
! 4019: }
! 4020: static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
! 4021: return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
! 4022: }
! 4023: static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
! 4024: ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
! 4025: }
! 4026: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
! 4027: return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
! 4028: }
! 4029: static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
! 4030: ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
! 4031: }
! 4032: static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
! 4033: return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
! 4034: }
! 4035: static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
! 4036: return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
! 4037: }
! 4038: static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
! 4039: return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
! 4040: }
! 4041: static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
! 4042: return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
! 4043: }
! 4044: static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
! 4045: return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
! 4046: }
! 4047: static int apndSetSystemCall(
! 4048: sqlite3_vfs *pVfs,
! 4049: const char *zName,
! 4050: sqlite3_syscall_ptr pCall
! 4051: ){
! 4052: return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
! 4053: }
! 4054: static sqlite3_syscall_ptr apndGetSystemCall(
! 4055: sqlite3_vfs *pVfs,
! 4056: const char *zName
! 4057: ){
! 4058: return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
! 4059: }
! 4060: static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
! 4061: return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
! 4062: }
! 4063:
! 4064:
! 4065: #ifdef _WIN32
! 4066:
! 4067: #endif
! 4068: /*
! 4069: ** This routine is called when the extension is loaded.
! 4070: ** Register the new VFS.
! 4071: */
! 4072: int sqlite3_appendvfs_init(
! 4073: sqlite3 *db,
! 4074: char **pzErrMsg,
! 4075: const sqlite3_api_routines *pApi
! 4076: ){
! 4077: int rc = SQLITE_OK;
! 4078: sqlite3_vfs *pOrig;
! 4079: SQLITE_EXTENSION_INIT2(pApi);
! 4080: (void)pzErrMsg;
! 4081: (void)db;
! 4082: pOrig = sqlite3_vfs_find(0);
! 4083: apnd_vfs.iVersion = pOrig->iVersion;
! 4084: apnd_vfs.pAppData = pOrig;
! 4085: apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
! 4086: rc = sqlite3_vfs_register(&apnd_vfs, 0);
! 4087: #ifdef APPENDVFS_TEST
! 4088: if( rc==SQLITE_OK ){
! 4089: rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
! 4090: }
! 4091: #endif
! 4092: if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
! 4093: return rc;
! 4094: }
! 4095:
! 4096: /************************* End ../ext/misc/appendvfs.c ********************/
! 4097: /************************* Begin ../ext/misc/memtrace.c ******************/
! 4098: /*
! 4099: ** 2019-01-21
! 4100: **
! 4101: ** The author disclaims copyright to this source code. In place of
! 4102: ** a legal notice, here is a blessing:
! 4103: **
! 4104: ** May you do good and not evil.
! 4105: ** May you find forgiveness for yourself and forgive others.
! 4106: ** May you share freely, never taking more than you give.
! 4107: **
! 4108: *************************************************************************
! 4109: **
! 4110: ** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
! 4111: ** mechanism to add a tracing layer on top of SQLite. If this extension
! 4112: ** is registered prior to sqlite3_initialize(), it will cause all memory
! 4113: ** allocation activities to be logged on standard output, or to some other
! 4114: ** FILE specified by the initializer.
! 4115: **
! 4116: ** This file needs to be compiled into the application that uses it.
! 4117: **
! 4118: ** This extension is used to implement the --memtrace option of the
! 4119: ** command-line shell.
! 4120: */
! 4121: #include <assert.h>
! 4122: #include <string.h>
! 4123: #include <stdio.h>
! 4124:
! 4125: /* The original memory allocation routines */
! 4126: static sqlite3_mem_methods memtraceBase;
! 4127: static FILE *memtraceOut;
! 4128:
! 4129: /* Methods that trace memory allocations */
! 4130: static void *memtraceMalloc(int n){
! 4131: if( memtraceOut ){
! 4132: fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
! 4133: memtraceBase.xRoundup(n));
! 4134: }
! 4135: return memtraceBase.xMalloc(n);
! 4136: }
! 4137: static void memtraceFree(void *p){
! 4138: if( p==0 ) return;
! 4139: if( memtraceOut ){
! 4140: fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
! 4141: }
! 4142: memtraceBase.xFree(p);
! 4143: }
! 4144: static void *memtraceRealloc(void *p, int n){
! 4145: if( p==0 ) return memtraceMalloc(n);
! 4146: if( n==0 ){
! 4147: memtraceFree(p);
! 4148: return 0;
! 4149: }
! 4150: if( memtraceOut ){
! 4151: fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
! 4152: memtraceBase.xSize(p), memtraceBase.xRoundup(n));
! 4153: }
! 4154: return memtraceBase.xRealloc(p, n);
! 4155: }
! 4156: static int memtraceSize(void *p){
! 4157: return memtraceBase.xSize(p);
! 4158: }
! 4159: static int memtraceRoundup(int n){
! 4160: return memtraceBase.xRoundup(n);
! 4161: }
! 4162: static int memtraceInit(void *p){
! 4163: return memtraceBase.xInit(p);
! 4164: }
! 4165: static void memtraceShutdown(void *p){
! 4166: memtraceBase.xShutdown(p);
! 4167: }
! 4168:
! 4169: /* The substitute memory allocator */
! 4170: static sqlite3_mem_methods ersaztMethods = {
! 4171: memtraceMalloc,
! 4172: memtraceFree,
! 4173: memtraceRealloc,
! 4174: memtraceSize,
! 4175: memtraceRoundup,
! 4176: memtraceInit,
! 4177: memtraceShutdown,
! 4178: 0
! 4179: };
! 4180:
! 4181: /* Begin tracing memory allocations to out. */
! 4182: int sqlite3MemTraceActivate(FILE *out){
! 4183: int rc = SQLITE_OK;
! 4184: if( memtraceBase.xMalloc==0 ){
! 4185: rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
! 4186: if( rc==SQLITE_OK ){
! 4187: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
! 4188: }
! 4189: }
! 4190: memtraceOut = out;
! 4191: return rc;
! 4192: }
! 4193:
! 4194: /* Deactivate memory tracing */
! 4195: int sqlite3MemTraceDeactivate(void){
! 4196: int rc = SQLITE_OK;
! 4197: if( memtraceBase.xMalloc!=0 ){
! 4198: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
! 4199: if( rc==SQLITE_OK ){
! 4200: memset(&memtraceBase, 0, sizeof(memtraceBase));
! 4201: }
! 4202: }
! 4203: memtraceOut = 0;
! 4204: return rc;
! 4205: }
! 4206:
! 4207: /************************* End ../ext/misc/memtrace.c ********************/
! 4208: #ifdef SQLITE_HAVE_ZLIB
! 4209: /************************* Begin ../ext/misc/zipfile.c ******************/
! 4210: /*
! 4211: ** 2017-12-26
! 4212: **
! 4213: ** The author disclaims copyright to this source code. In place of
! 4214: ** a legal notice, here is a blessing:
! 4215: **
! 4216: ** May you do good and not evil.
! 4217: ** May you find forgiveness for yourself and forgive others.
! 4218: ** May you share freely, never taking more than you give.
! 4219: **
! 4220: ******************************************************************************
! 4221: **
! 4222: ** This file implements a virtual table for reading and writing ZIP archive
! 4223: ** files.
! 4224: **
! 4225: ** Usage example:
! 4226: **
! 4227: ** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
! 4228: **
! 4229: ** Current limitations:
! 4230: **
! 4231: ** * No support for encryption
! 4232: ** * No support for ZIP archives spanning multiple files
! 4233: ** * No support for zip64 extensions
! 4234: ** * Only the "inflate/deflate" (zlib) compression method is supported
! 4235: */
! 4236: /* #include "sqlite3ext.h" */
! 4237: SQLITE_EXTENSION_INIT1
! 4238: #include <stdio.h>
! 4239: #include <string.h>
! 4240: #include <assert.h>
! 4241:
! 4242: #include <zlib.h>
! 4243:
! 4244: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 4245:
! 4246: #ifndef SQLITE_AMALGAMATION
! 4247:
! 4248: /* typedef sqlite3_int64 i64; */
! 4249: /* typedef unsigned char u8; */
! 4250: typedef unsigned short u16;
! 4251: typedef unsigned long u32;
! 4252: #define MIN(a,b) ((a)<(b) ? (a) : (b))
! 4253:
! 4254: #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
! 4255: # define ALWAYS(X) (1)
! 4256: # define NEVER(X) (0)
! 4257: #elif !defined(NDEBUG)
! 4258: # define ALWAYS(X) ((X)?1:(assert(0),0))
! 4259: # define NEVER(X) ((X)?(assert(0),1):0)
! 4260: #else
! 4261: # define ALWAYS(X) (X)
! 4262: # define NEVER(X) (X)
! 4263: #endif
! 4264:
! 4265: #endif /* SQLITE_AMALGAMATION */
! 4266:
! 4267: /*
! 4268: ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
! 4269: **
! 4270: ** In some ways it would be better to obtain these values from system
! 4271: ** header files. But, the dependency is undesirable and (a) these
! 4272: ** have been stable for decades, (b) the values are part of POSIX and
! 4273: ** are also made explicit in [man stat], and (c) are part of the
! 4274: ** file format for zip archives.
! 4275: */
! 4276: #ifndef S_IFDIR
! 4277: # define S_IFDIR 0040000
! 4278: #endif
! 4279: #ifndef S_IFREG
! 4280: # define S_IFREG 0100000
! 4281: #endif
! 4282: #ifndef S_IFLNK
! 4283: # define S_IFLNK 0120000
! 4284: #endif
! 4285:
! 4286: static const char ZIPFILE_SCHEMA[] =
! 4287: "CREATE TABLE y("
! 4288: "name PRIMARY KEY," /* 0: Name of file in zip archive */
! 4289: "mode," /* 1: POSIX mode for file */
! 4290: "mtime," /* 2: Last modification time (secs since 1970)*/
! 4291: "sz," /* 3: Size of object */
! 4292: "rawdata," /* 4: Raw data */
! 4293: "data," /* 5: Uncompressed data */
! 4294: "method," /* 6: Compression method (integer) */
! 4295: "z HIDDEN" /* 7: Name of zip file */
! 4296: ") WITHOUT ROWID;";
! 4297:
! 4298: #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
! 4299: #define ZIPFILE_BUFFER_SIZE (64*1024)
! 4300:
! 4301:
! 4302: /*
! 4303: ** Magic numbers used to read and write zip files.
! 4304: **
! 4305: ** ZIPFILE_NEWENTRY_MADEBY:
! 4306: ** Use this value for the "version-made-by" field in new zip file
! 4307: ** entries. The upper byte indicates "unix", and the lower byte
! 4308: ** indicates that the zip file matches pkzip specification 3.0.
! 4309: ** This is what info-zip seems to do.
! 4310: **
! 4311: ** ZIPFILE_NEWENTRY_REQUIRED:
! 4312: ** Value for "version-required-to-extract" field of new entries.
! 4313: ** Version 2.0 is required to support folders and deflate compression.
! 4314: **
! 4315: ** ZIPFILE_NEWENTRY_FLAGS:
! 4316: ** Value for "general-purpose-bit-flags" field of new entries. Bit
! 4317: ** 11 means "utf-8 filename and comment".
! 4318: **
! 4319: ** ZIPFILE_SIGNATURE_CDS:
! 4320: ** First 4 bytes of a valid CDS record.
! 4321: **
! 4322: ** ZIPFILE_SIGNATURE_LFH:
! 4323: ** First 4 bytes of a valid LFH record.
! 4324: **
! 4325: ** ZIPFILE_SIGNATURE_EOCD
! 4326: ** First 4 bytes of a valid EOCD record.
! 4327: */
! 4328: #define ZIPFILE_EXTRA_TIMESTAMP 0x5455
! 4329: #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
! 4330: #define ZIPFILE_NEWENTRY_REQUIRED 20
! 4331: #define ZIPFILE_NEWENTRY_FLAGS 0x800
! 4332: #define ZIPFILE_SIGNATURE_CDS 0x02014b50
! 4333: #define ZIPFILE_SIGNATURE_LFH 0x04034b50
! 4334: #define ZIPFILE_SIGNATURE_EOCD 0x06054b50
! 4335:
! 4336: /*
! 4337: ** The sizes of the fixed-size part of each of the three main data
! 4338: ** structures in a zip archive.
! 4339: */
! 4340: #define ZIPFILE_LFH_FIXED_SZ 30
! 4341: #define ZIPFILE_EOCD_FIXED_SZ 22
! 4342: #define ZIPFILE_CDS_FIXED_SZ 46
! 4343:
! 4344: /*
! 4345: *** 4.3.16 End of central directory record:
! 4346: ***
! 4347: *** end of central dir signature 4 bytes (0x06054b50)
! 4348: *** number of this disk 2 bytes
! 4349: *** number of the disk with the
! 4350: *** start of the central directory 2 bytes
! 4351: *** total number of entries in the
! 4352: *** central directory on this disk 2 bytes
! 4353: *** total number of entries in
! 4354: *** the central directory 2 bytes
! 4355: *** size of the central directory 4 bytes
! 4356: *** offset of start of central
! 4357: *** directory with respect to
! 4358: *** the starting disk number 4 bytes
! 4359: *** .ZIP file comment length 2 bytes
! 4360: *** .ZIP file comment (variable size)
! 4361: */
! 4362: typedef struct ZipfileEOCD ZipfileEOCD;
! 4363: struct ZipfileEOCD {
! 4364: u16 iDisk;
! 4365: u16 iFirstDisk;
! 4366: u16 nEntry;
! 4367: u16 nEntryTotal;
! 4368: u32 nSize;
! 4369: u32 iOffset;
! 4370: };
! 4371:
! 4372: /*
! 4373: *** 4.3.12 Central directory structure:
! 4374: ***
! 4375: *** ...
! 4376: ***
! 4377: *** central file header signature 4 bytes (0x02014b50)
! 4378: *** version made by 2 bytes
! 4379: *** version needed to extract 2 bytes
! 4380: *** general purpose bit flag 2 bytes
! 4381: *** compression method 2 bytes
! 4382: *** last mod file time 2 bytes
! 4383: *** last mod file date 2 bytes
! 4384: *** crc-32 4 bytes
! 4385: *** compressed size 4 bytes
! 4386: *** uncompressed size 4 bytes
! 4387: *** file name length 2 bytes
! 4388: *** extra field length 2 bytes
! 4389: *** file comment length 2 bytes
! 4390: *** disk number start 2 bytes
! 4391: *** internal file attributes 2 bytes
! 4392: *** external file attributes 4 bytes
! 4393: *** relative offset of local header 4 bytes
! 4394: */
! 4395: typedef struct ZipfileCDS ZipfileCDS;
! 4396: struct ZipfileCDS {
! 4397: u16 iVersionMadeBy;
! 4398: u16 iVersionExtract;
! 4399: u16 flags;
! 4400: u16 iCompression;
! 4401: u16 mTime;
! 4402: u16 mDate;
! 4403: u32 crc32;
! 4404: u32 szCompressed;
! 4405: u32 szUncompressed;
! 4406: u16 nFile;
! 4407: u16 nExtra;
! 4408: u16 nComment;
! 4409: u16 iDiskStart;
! 4410: u16 iInternalAttr;
! 4411: u32 iExternalAttr;
! 4412: u32 iOffset;
! 4413: char *zFile; /* Filename (sqlite3_malloc()) */
! 4414: };
! 4415:
! 4416: /*
! 4417: *** 4.3.7 Local file header:
! 4418: ***
! 4419: *** local file header signature 4 bytes (0x04034b50)
! 4420: *** version needed to extract 2 bytes
! 4421: *** general purpose bit flag 2 bytes
! 4422: *** compression method 2 bytes
! 4423: *** last mod file time 2 bytes
! 4424: *** last mod file date 2 bytes
! 4425: *** crc-32 4 bytes
! 4426: *** compressed size 4 bytes
! 4427: *** uncompressed size 4 bytes
! 4428: *** file name length 2 bytes
! 4429: *** extra field length 2 bytes
! 4430: ***
! 4431: */
! 4432: typedef struct ZipfileLFH ZipfileLFH;
! 4433: struct ZipfileLFH {
! 4434: u16 iVersionExtract;
! 4435: u16 flags;
! 4436: u16 iCompression;
! 4437: u16 mTime;
! 4438: u16 mDate;
! 4439: u32 crc32;
! 4440: u32 szCompressed;
! 4441: u32 szUncompressed;
! 4442: u16 nFile;
! 4443: u16 nExtra;
! 4444: };
! 4445:
! 4446: typedef struct ZipfileEntry ZipfileEntry;
! 4447: struct ZipfileEntry {
! 4448: ZipfileCDS cds; /* Parsed CDS record */
! 4449: u32 mUnixTime; /* Modification time, in UNIX format */
! 4450: u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
! 4451: i64 iDataOff; /* Offset to data in file (if aData==0) */
! 4452: u8 *aData; /* cds.szCompressed bytes of compressed data */
! 4453: ZipfileEntry *pNext; /* Next element in in-memory CDS */
! 4454: };
! 4455:
! 4456: /*
! 4457: ** Cursor type for zipfile tables.
! 4458: */
! 4459: typedef struct ZipfileCsr ZipfileCsr;
! 4460: struct ZipfileCsr {
! 4461: sqlite3_vtab_cursor base; /* Base class - must be first */
! 4462: i64 iId; /* Cursor ID */
! 4463: u8 bEof; /* True when at EOF */
! 4464: u8 bNoop; /* If next xNext() call is no-op */
! 4465:
! 4466: /* Used outside of write transactions */
! 4467: FILE *pFile; /* Zip file */
! 4468: i64 iNextOff; /* Offset of next record in central directory */
! 4469: ZipfileEOCD eocd; /* Parse of central directory record */
! 4470:
! 4471: ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
! 4472: ZipfileEntry *pCurrent; /* Current entry */
! 4473: ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
! 4474: };
! 4475:
! 4476: typedef struct ZipfileTab ZipfileTab;
! 4477: struct ZipfileTab {
! 4478: sqlite3_vtab base; /* Base class - must be first */
! 4479: char *zFile; /* Zip file this table accesses (may be NULL) */
! 4480: sqlite3 *db; /* Host database connection */
! 4481: u8 *aBuffer; /* Temporary buffer used for various tasks */
! 4482:
! 4483: ZipfileCsr *pCsrList; /* List of cursors */
! 4484: i64 iNextCsrid;
! 4485:
! 4486: /* The following are used by write transactions only */
! 4487: ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
! 4488: ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
! 4489: FILE *pWriteFd; /* File handle open on zip archive */
! 4490: i64 szCurrent; /* Current size of zip archive */
! 4491: i64 szOrig; /* Size of archive at start of transaction */
! 4492: };
! 4493:
! 4494: /*
! 4495: ** Set the error message contained in context ctx to the results of
! 4496: ** vprintf(zFmt, ...).
! 4497: */
! 4498: static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
! 4499: char *zMsg = 0;
! 4500: va_list ap;
! 4501: va_start(ap, zFmt);
! 4502: zMsg = sqlite3_vmprintf(zFmt, ap);
! 4503: sqlite3_result_error(ctx, zMsg, -1);
! 4504: sqlite3_free(zMsg);
! 4505: va_end(ap);
! 4506: }
! 4507:
! 4508: /*
! 4509: ** If string zIn is quoted, dequote it in place. Otherwise, if the string
! 4510: ** is not quoted, do nothing.
! 4511: */
! 4512: static void zipfileDequote(char *zIn){
! 4513: char q = zIn[0];
! 4514: if( q=='"' || q=='\'' || q=='`' || q=='[' ){
! 4515: int iIn = 1;
! 4516: int iOut = 0;
! 4517: if( q=='[' ) q = ']';
! 4518: while( ALWAYS(zIn[iIn]) ){
! 4519: char c = zIn[iIn++];
! 4520: if( c==q && zIn[iIn++]!=q ) break;
! 4521: zIn[iOut++] = c;
! 4522: }
! 4523: zIn[iOut] = '\0';
! 4524: }
! 4525: }
! 4526:
! 4527: /*
! 4528: ** Construct a new ZipfileTab virtual table object.
! 4529: **
! 4530: ** argv[0] -> module name ("zipfile")
! 4531: ** argv[1] -> database name
! 4532: ** argv[2] -> table name
! 4533: ** argv[...] -> "column name" and other module argument fields.
! 4534: */
! 4535: static int zipfileConnect(
! 4536: sqlite3 *db,
! 4537: void *pAux,
! 4538: int argc, const char *const*argv,
! 4539: sqlite3_vtab **ppVtab,
! 4540: char **pzErr
! 4541: ){
! 4542: int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
! 4543: int nFile = 0;
! 4544: const char *zFile = 0;
! 4545: ZipfileTab *pNew = 0;
! 4546: int rc;
! 4547:
! 4548: /* If the table name is not "zipfile", require that the argument be
! 4549: ** specified. This stops zipfile tables from being created as:
! 4550: **
! 4551: ** CREATE VIRTUAL TABLE zzz USING zipfile();
! 4552: **
! 4553: ** It does not prevent:
! 4554: **
! 4555: ** CREATE VIRTUAL TABLE zipfile USING zipfile();
! 4556: */
! 4557: assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
! 4558: if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
! 4559: *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
! 4560: return SQLITE_ERROR;
! 4561: }
! 4562:
! 4563: if( argc>3 ){
! 4564: zFile = argv[3];
! 4565: nFile = (int)strlen(zFile)+1;
! 4566: }
! 4567:
! 4568: rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
! 4569: if( rc==SQLITE_OK ){
! 4570: pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
! 4571: if( pNew==0 ) return SQLITE_NOMEM;
! 4572: memset(pNew, 0, nByte+nFile);
! 4573: pNew->db = db;
! 4574: pNew->aBuffer = (u8*)&pNew[1];
! 4575: if( zFile ){
! 4576: pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
! 4577: memcpy(pNew->zFile, zFile, nFile);
! 4578: zipfileDequote(pNew->zFile);
! 4579: }
! 4580: }
! 4581: *ppVtab = (sqlite3_vtab*)pNew;
! 4582: return rc;
! 4583: }
! 4584:
! 4585: /*
! 4586: ** Free the ZipfileEntry structure indicated by the only argument.
! 4587: */
! 4588: static void zipfileEntryFree(ZipfileEntry *p){
! 4589: if( p ){
! 4590: sqlite3_free(p->cds.zFile);
! 4591: sqlite3_free(p);
! 4592: }
! 4593: }
! 4594:
! 4595: /*
! 4596: ** Release resources that should be freed at the end of a write
! 4597: ** transaction.
! 4598: */
! 4599: static void zipfileCleanupTransaction(ZipfileTab *pTab){
! 4600: ZipfileEntry *pEntry;
! 4601: ZipfileEntry *pNext;
! 4602:
! 4603: if( pTab->pWriteFd ){
! 4604: fclose(pTab->pWriteFd);
! 4605: pTab->pWriteFd = 0;
! 4606: }
! 4607: for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
! 4608: pNext = pEntry->pNext;
! 4609: zipfileEntryFree(pEntry);
! 4610: }
! 4611: pTab->pFirstEntry = 0;
! 4612: pTab->pLastEntry = 0;
! 4613: pTab->szCurrent = 0;
! 4614: pTab->szOrig = 0;
! 4615: }
! 4616:
! 4617: /*
! 4618: ** This method is the destructor for zipfile vtab objects.
! 4619: */
! 4620: static int zipfileDisconnect(sqlite3_vtab *pVtab){
! 4621: zipfileCleanupTransaction((ZipfileTab*)pVtab);
! 4622: sqlite3_free(pVtab);
! 4623: return SQLITE_OK;
! 4624: }
! 4625:
! 4626: /*
! 4627: ** Constructor for a new ZipfileCsr object.
! 4628: */
! 4629: static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
! 4630: ZipfileTab *pTab = (ZipfileTab*)p;
! 4631: ZipfileCsr *pCsr;
! 4632: pCsr = sqlite3_malloc(sizeof(*pCsr));
! 4633: *ppCsr = (sqlite3_vtab_cursor*)pCsr;
! 4634: if( pCsr==0 ){
! 4635: return SQLITE_NOMEM;
! 4636: }
! 4637: memset(pCsr, 0, sizeof(*pCsr));
! 4638: pCsr->iId = ++pTab->iNextCsrid;
! 4639: pCsr->pCsrNext = pTab->pCsrList;
! 4640: pTab->pCsrList = pCsr;
! 4641: return SQLITE_OK;
! 4642: }
! 4643:
! 4644: /*
! 4645: ** Reset a cursor back to the state it was in when first returned
! 4646: ** by zipfileOpen().
! 4647: */
! 4648: static void zipfileResetCursor(ZipfileCsr *pCsr){
! 4649: ZipfileEntry *p;
! 4650: ZipfileEntry *pNext;
! 4651:
! 4652: pCsr->bEof = 0;
! 4653: if( pCsr->pFile ){
! 4654: fclose(pCsr->pFile);
! 4655: pCsr->pFile = 0;
! 4656: zipfileEntryFree(pCsr->pCurrent);
! 4657: pCsr->pCurrent = 0;
! 4658: }
! 4659:
! 4660: for(p=pCsr->pFreeEntry; p; p=pNext){
! 4661: pNext = p->pNext;
! 4662: zipfileEntryFree(p);
! 4663: }
! 4664: }
! 4665:
! 4666: /*
! 4667: ** Destructor for an ZipfileCsr.
! 4668: */
! 4669: static int zipfileClose(sqlite3_vtab_cursor *cur){
! 4670: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 4671: ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
! 4672: ZipfileCsr **pp;
! 4673: zipfileResetCursor(pCsr);
! 4674:
! 4675: /* Remove this cursor from the ZipfileTab.pCsrList list. */
! 4676: for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
! 4677: *pp = pCsr->pCsrNext;
! 4678:
! 4679: sqlite3_free(pCsr);
! 4680: return SQLITE_OK;
! 4681: }
! 4682:
! 4683: /*
! 4684: ** Set the error message for the virtual table associated with cursor
! 4685: ** pCsr to the results of vprintf(zFmt, ...).
! 4686: */
! 4687: static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
! 4688: va_list ap;
! 4689: va_start(ap, zFmt);
! 4690: sqlite3_free(pTab->base.zErrMsg);
! 4691: pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 4692: va_end(ap);
! 4693: }
! 4694: static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
! 4695: va_list ap;
! 4696: va_start(ap, zFmt);
! 4697: sqlite3_free(pCsr->base.pVtab->zErrMsg);
! 4698: pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 4699: va_end(ap);
! 4700: }
! 4701:
! 4702: /*
! 4703: ** Read nRead bytes of data from offset iOff of file pFile into buffer
! 4704: ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
! 4705: ** otherwise.
! 4706: **
! 4707: ** If an error does occur, output variable (*pzErrmsg) may be set to point
! 4708: ** to an English language error message. It is the responsibility of the
! 4709: ** caller to eventually free this buffer using
! 4710: ** sqlite3_free().
! 4711: */
! 4712: static int zipfileReadData(
! 4713: FILE *pFile, /* Read from this file */
! 4714: u8 *aRead, /* Read into this buffer */
! 4715: int nRead, /* Number of bytes to read */
! 4716: i64 iOff, /* Offset to read from */
! 4717: char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
! 4718: ){
! 4719: size_t n;
! 4720: fseek(pFile, (long)iOff, SEEK_SET);
! 4721: n = fread(aRead, 1, nRead, pFile);
! 4722: if( (int)n!=nRead ){
! 4723: *pzErrmsg = sqlite3_mprintf("error in fread()");
! 4724: return SQLITE_ERROR;
! 4725: }
! 4726: return SQLITE_OK;
! 4727: }
! 4728:
! 4729: static int zipfileAppendData(
! 4730: ZipfileTab *pTab,
! 4731: const u8 *aWrite,
! 4732: int nWrite
! 4733: ){
! 4734: size_t n;
! 4735: fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
! 4736: n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
! 4737: if( (int)n!=nWrite ){
! 4738: pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
! 4739: return SQLITE_ERROR;
! 4740: }
! 4741: pTab->szCurrent += nWrite;
! 4742: return SQLITE_OK;
! 4743: }
! 4744:
! 4745: /*
! 4746: ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
! 4747: */
! 4748: static u16 zipfileGetU16(const u8 *aBuf){
! 4749: return (aBuf[1] << 8) + aBuf[0];
! 4750: }
! 4751:
! 4752: /*
! 4753: ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
! 4754: */
! 4755: static u32 zipfileGetU32(const u8 *aBuf){
! 4756: return ((u32)(aBuf[3]) << 24)
! 4757: + ((u32)(aBuf[2]) << 16)
! 4758: + ((u32)(aBuf[1]) << 8)
! 4759: + ((u32)(aBuf[0]) << 0);
! 4760: }
! 4761:
! 4762: /*
! 4763: ** Write a 16-bit little endiate integer into buffer aBuf.
! 4764: */
! 4765: static void zipfilePutU16(u8 *aBuf, u16 val){
! 4766: aBuf[0] = val & 0xFF;
! 4767: aBuf[1] = (val>>8) & 0xFF;
! 4768: }
! 4769:
! 4770: /*
! 4771: ** Write a 32-bit little endiate integer into buffer aBuf.
! 4772: */
! 4773: static void zipfilePutU32(u8 *aBuf, u32 val){
! 4774: aBuf[0] = val & 0xFF;
! 4775: aBuf[1] = (val>>8) & 0xFF;
! 4776: aBuf[2] = (val>>16) & 0xFF;
! 4777: aBuf[3] = (val>>24) & 0xFF;
! 4778: }
! 4779:
! 4780: #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
! 4781: #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
! 4782:
! 4783: #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
! 4784: #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
! 4785:
! 4786: /*
! 4787: ** Magic numbers used to read CDS records.
! 4788: */
! 4789: #define ZIPFILE_CDS_NFILE_OFF 28
! 4790: #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
! 4791:
! 4792: /*
! 4793: ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
! 4794: ** if the record is not well-formed, or SQLITE_OK otherwise.
! 4795: */
! 4796: static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
! 4797: u8 *aRead = aBuf;
! 4798: u32 sig = zipfileRead32(aRead);
! 4799: int rc = SQLITE_OK;
! 4800: if( sig!=ZIPFILE_SIGNATURE_CDS ){
! 4801: rc = SQLITE_ERROR;
! 4802: }else{
! 4803: pCDS->iVersionMadeBy = zipfileRead16(aRead);
! 4804: pCDS->iVersionExtract = zipfileRead16(aRead);
! 4805: pCDS->flags = zipfileRead16(aRead);
! 4806: pCDS->iCompression = zipfileRead16(aRead);
! 4807: pCDS->mTime = zipfileRead16(aRead);
! 4808: pCDS->mDate = zipfileRead16(aRead);
! 4809: pCDS->crc32 = zipfileRead32(aRead);
! 4810: pCDS->szCompressed = zipfileRead32(aRead);
! 4811: pCDS->szUncompressed = zipfileRead32(aRead);
! 4812: assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
! 4813: pCDS->nFile = zipfileRead16(aRead);
! 4814: pCDS->nExtra = zipfileRead16(aRead);
! 4815: pCDS->nComment = zipfileRead16(aRead);
! 4816: pCDS->iDiskStart = zipfileRead16(aRead);
! 4817: pCDS->iInternalAttr = zipfileRead16(aRead);
! 4818: pCDS->iExternalAttr = zipfileRead32(aRead);
! 4819: pCDS->iOffset = zipfileRead32(aRead);
! 4820: assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
! 4821: }
! 4822:
! 4823: return rc;
! 4824: }
! 4825:
! 4826: /*
! 4827: ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
! 4828: ** if the record is not well-formed, or SQLITE_OK otherwise.
! 4829: */
! 4830: static int zipfileReadLFH(
! 4831: u8 *aBuffer,
! 4832: ZipfileLFH *pLFH
! 4833: ){
! 4834: u8 *aRead = aBuffer;
! 4835: int rc = SQLITE_OK;
! 4836:
! 4837: u32 sig = zipfileRead32(aRead);
! 4838: if( sig!=ZIPFILE_SIGNATURE_LFH ){
! 4839: rc = SQLITE_ERROR;
! 4840: }else{
! 4841: pLFH->iVersionExtract = zipfileRead16(aRead);
! 4842: pLFH->flags = zipfileRead16(aRead);
! 4843: pLFH->iCompression = zipfileRead16(aRead);
! 4844: pLFH->mTime = zipfileRead16(aRead);
! 4845: pLFH->mDate = zipfileRead16(aRead);
! 4846: pLFH->crc32 = zipfileRead32(aRead);
! 4847: pLFH->szCompressed = zipfileRead32(aRead);
! 4848: pLFH->szUncompressed = zipfileRead32(aRead);
! 4849: pLFH->nFile = zipfileRead16(aRead);
! 4850: pLFH->nExtra = zipfileRead16(aRead);
! 4851: }
! 4852: return rc;
! 4853: }
! 4854:
! 4855:
! 4856: /*
! 4857: ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
! 4858: ** Scan through this buffer to find an "extra-timestamp" field. If one
! 4859: ** exists, extract the 32-bit modification-timestamp from it and store
! 4860: ** the value in output parameter *pmTime.
! 4861: **
! 4862: ** Zero is returned if no extra-timestamp record could be found (and so
! 4863: ** *pmTime is left unchanged), or non-zero otherwise.
! 4864: **
! 4865: ** The general format of an extra field is:
! 4866: **
! 4867: ** Header ID 2 bytes
! 4868: ** Data Size 2 bytes
! 4869: ** Data N bytes
! 4870: */
! 4871: static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
! 4872: int ret = 0;
! 4873: u8 *p = aExtra;
! 4874: u8 *pEnd = &aExtra[nExtra];
! 4875:
! 4876: while( p<pEnd ){
! 4877: u16 id = zipfileRead16(p);
! 4878: u16 nByte = zipfileRead16(p);
! 4879:
! 4880: switch( id ){
! 4881: case ZIPFILE_EXTRA_TIMESTAMP: {
! 4882: u8 b = p[0];
! 4883: if( b & 0x01 ){ /* 0x01 -> modtime is present */
! 4884: *pmTime = zipfileGetU32(&p[1]);
! 4885: ret = 1;
! 4886: }
! 4887: break;
! 4888: }
! 4889: }
! 4890:
! 4891: p += nByte;
! 4892: }
! 4893: return ret;
! 4894: }
! 4895:
! 4896: /*
! 4897: ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
! 4898: ** fields of the CDS structure passed as the only argument to a 32-bit
! 4899: ** UNIX seconds-since-the-epoch timestamp. Return the result.
! 4900: **
! 4901: ** "Standard" MS-DOS time format:
! 4902: **
! 4903: ** File modification time:
! 4904: ** Bits 00-04: seconds divided by 2
! 4905: ** Bits 05-10: minute
! 4906: ** Bits 11-15: hour
! 4907: ** File modification date:
! 4908: ** Bits 00-04: day
! 4909: ** Bits 05-08: month (1-12)
! 4910: ** Bits 09-15: years from 1980
! 4911: **
! 4912: ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
! 4913: */
! 4914: static u32 zipfileMtime(ZipfileCDS *pCDS){
! 4915: int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
! 4916: int M = ((pCDS->mDate >> 5) & 0x0F);
! 4917: int D = (pCDS->mDate & 0x1F);
! 4918: int B = -13;
! 4919:
! 4920: int sec = (pCDS->mTime & 0x1F)*2;
! 4921: int min = (pCDS->mTime >> 5) & 0x3F;
! 4922: int hr = (pCDS->mTime >> 11) & 0x1F;
! 4923: i64 JD;
! 4924:
! 4925: /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
! 4926:
! 4927: /* Calculate the JD in seconds for noon on the day in question */
! 4928: if( M<3 ){
! 4929: Y = Y-1;
! 4930: M = M+12;
! 4931: }
! 4932: JD = (i64)(24*60*60) * (
! 4933: (int)(365.25 * (Y + 4716))
! 4934: + (int)(30.6001 * (M + 1))
! 4935: + D + B - 1524
! 4936: );
! 4937:
! 4938: /* Correct the JD for the time within the day */
! 4939: JD += (hr-12) * 3600 + min * 60 + sec;
! 4940:
! 4941: /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
! 4942: return (u32)(JD - (i64)(24405875) * 24*60*6);
! 4943: }
! 4944:
! 4945: /*
! 4946: ** The opposite of zipfileMtime(). This function populates the mTime and
! 4947: ** mDate fields of the CDS structure passed as the first argument according
! 4948: ** to the UNIX timestamp value passed as the second.
! 4949: */
! 4950: static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
! 4951: /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
! 4952: i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
! 4953:
! 4954: int A, B, C, D, E;
! 4955: int yr, mon, day;
! 4956: int hr, min, sec;
! 4957:
! 4958: A = (int)((JD - 1867216.25)/36524.25);
! 4959: A = (int)(JD + 1 + A - (A/4));
! 4960: B = A + 1524;
! 4961: C = (int)((B - 122.1)/365.25);
! 4962: D = (36525*(C&32767))/100;
! 4963: E = (int)((B-D)/30.6001);
! 4964:
! 4965: day = B - D - (int)(30.6001*E);
! 4966: mon = (E<14 ? E-1 : E-13);
! 4967: yr = mon>2 ? C-4716 : C-4715;
! 4968:
! 4969: hr = (mUnixTime % (24*60*60)) / (60*60);
! 4970: min = (mUnixTime % (60*60)) / 60;
! 4971: sec = (mUnixTime % 60);
! 4972:
! 4973: if( yr>=1980 ){
! 4974: pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
! 4975: pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
! 4976: }else{
! 4977: pCds->mDate = pCds->mTime = 0;
! 4978: }
! 4979:
! 4980: assert( mUnixTime<315507600
! 4981: || mUnixTime==zipfileMtime(pCds)
! 4982: || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
! 4983: /* || (mUnixTime % 2) */
! 4984: );
! 4985: }
! 4986:
! 4987: /*
! 4988: ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
! 4989: ** size) containing an entire zip archive image. Or, if aBlob is NULL,
! 4990: ** then pFile is a file-handle open on a zip file. In either case, this
! 4991: ** function creates a ZipfileEntry object based on the zip archive entry
! 4992: ** for which the CDS record is at offset iOff.
! 4993: **
! 4994: ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
! 4995: ** the new object. Otherwise, an SQLite error code is returned and the
! 4996: ** final value of (*ppEntry) undefined.
! 4997: */
! 4998: static int zipfileGetEntry(
! 4999: ZipfileTab *pTab, /* Store any error message here */
! 5000: const u8 *aBlob, /* Pointer to in-memory file image */
! 5001: int nBlob, /* Size of aBlob[] in bytes */
! 5002: FILE *pFile, /* If aBlob==0, read from this file */
! 5003: i64 iOff, /* Offset of CDS record */
! 5004: ZipfileEntry **ppEntry /* OUT: Pointer to new object */
! 5005: ){
! 5006: u8 *aRead;
! 5007: char **pzErr = &pTab->base.zErrMsg;
! 5008: int rc = SQLITE_OK;
! 5009:
! 5010: if( aBlob==0 ){
! 5011: aRead = pTab->aBuffer;
! 5012: rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
! 5013: }else{
! 5014: aRead = (u8*)&aBlob[iOff];
! 5015: }
! 5016:
! 5017: if( rc==SQLITE_OK ){
! 5018: sqlite3_int64 nAlloc;
! 5019: ZipfileEntry *pNew;
! 5020:
! 5021: int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
! 5022: int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
! 5023: nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
! 5024:
! 5025: nAlloc = sizeof(ZipfileEntry) + nExtra;
! 5026: if( aBlob ){
! 5027: nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
! 5028: }
! 5029:
! 5030: pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
! 5031: if( pNew==0 ){
! 5032: rc = SQLITE_NOMEM;
! 5033: }else{
! 5034: memset(pNew, 0, sizeof(ZipfileEntry));
! 5035: rc = zipfileReadCDS(aRead, &pNew->cds);
! 5036: if( rc!=SQLITE_OK ){
! 5037: *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
! 5038: }else if( aBlob==0 ){
! 5039: rc = zipfileReadData(
! 5040: pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
! 5041: );
! 5042: }else{
! 5043: aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
! 5044: }
! 5045: }
! 5046:
! 5047: if( rc==SQLITE_OK ){
! 5048: u32 *pt = &pNew->mUnixTime;
! 5049: pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
! 5050: pNew->aExtra = (u8*)&pNew[1];
! 5051: memcpy(pNew->aExtra, &aRead[nFile], nExtra);
! 5052: if( pNew->cds.zFile==0 ){
! 5053: rc = SQLITE_NOMEM;
! 5054: }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
! 5055: pNew->mUnixTime = zipfileMtime(&pNew->cds);
! 5056: }
! 5057: }
! 5058:
! 5059: if( rc==SQLITE_OK ){
! 5060: static const int szFix = ZIPFILE_LFH_FIXED_SZ;
! 5061: ZipfileLFH lfh;
! 5062: if( pFile ){
! 5063: rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
! 5064: }else{
! 5065: aRead = (u8*)&aBlob[pNew->cds.iOffset];
! 5066: }
! 5067:
! 5068: rc = zipfileReadLFH(aRead, &lfh);
! 5069: if( rc==SQLITE_OK ){
! 5070: pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
! 5071: pNew->iDataOff += lfh.nFile + lfh.nExtra;
! 5072: if( aBlob && pNew->cds.szCompressed ){
! 5073: pNew->aData = &pNew->aExtra[nExtra];
! 5074: memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
! 5075: }
! 5076: }else{
! 5077: *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
! 5078: (int)pNew->cds.iOffset
! 5079: );
! 5080: }
! 5081: }
! 5082:
! 5083: if( rc!=SQLITE_OK ){
! 5084: zipfileEntryFree(pNew);
! 5085: }else{
! 5086: *ppEntry = pNew;
! 5087: }
! 5088: }
! 5089:
! 5090: return rc;
! 5091: }
! 5092:
! 5093: /*
! 5094: ** Advance an ZipfileCsr to its next row of output.
! 5095: */
! 5096: static int zipfileNext(sqlite3_vtab_cursor *cur){
! 5097: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 5098: int rc = SQLITE_OK;
! 5099:
! 5100: if( pCsr->pFile ){
! 5101: i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
! 5102: zipfileEntryFree(pCsr->pCurrent);
! 5103: pCsr->pCurrent = 0;
! 5104: if( pCsr->iNextOff>=iEof ){
! 5105: pCsr->bEof = 1;
! 5106: }else{
! 5107: ZipfileEntry *p = 0;
! 5108: ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
! 5109: rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
! 5110: if( rc==SQLITE_OK ){
! 5111: pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
! 5112: pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
! 5113: }
! 5114: pCsr->pCurrent = p;
! 5115: }
! 5116: }else{
! 5117: if( !pCsr->bNoop ){
! 5118: pCsr->pCurrent = pCsr->pCurrent->pNext;
! 5119: }
! 5120: if( pCsr->pCurrent==0 ){
! 5121: pCsr->bEof = 1;
! 5122: }
! 5123: }
! 5124:
! 5125: pCsr->bNoop = 0;
! 5126: return rc;
! 5127: }
! 5128:
! 5129: static void zipfileFree(void *p) {
! 5130: sqlite3_free(p);
! 5131: }
! 5132:
! 5133: /*
! 5134: ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
! 5135: ** size is nOut bytes. This function uncompresses the data and sets the
! 5136: ** return value in context pCtx to the result (a blob).
! 5137: **
! 5138: ** If an error occurs, an error code is left in pCtx instead.
! 5139: */
! 5140: static void zipfileInflate(
! 5141: sqlite3_context *pCtx, /* Store result here */
! 5142: const u8 *aIn, /* Compressed data */
! 5143: int nIn, /* Size of buffer aIn[] in bytes */
! 5144: int nOut /* Expected output size */
! 5145: ){
! 5146: u8 *aRes = sqlite3_malloc(nOut);
! 5147: if( aRes==0 ){
! 5148: sqlite3_result_error_nomem(pCtx);
! 5149: }else{
! 5150: int err;
! 5151: z_stream str;
! 5152: memset(&str, 0, sizeof(str));
! 5153:
! 5154: str.next_in = (Byte*)aIn;
! 5155: str.avail_in = nIn;
! 5156: str.next_out = (Byte*)aRes;
! 5157: str.avail_out = nOut;
! 5158:
! 5159: err = inflateInit2(&str, -15);
! 5160: if( err!=Z_OK ){
! 5161: zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
! 5162: }else{
! 5163: err = inflate(&str, Z_NO_FLUSH);
! 5164: if( err!=Z_STREAM_END ){
! 5165: zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
! 5166: }else{
! 5167: sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
! 5168: aRes = 0;
! 5169: }
! 5170: }
! 5171: sqlite3_free(aRes);
! 5172: inflateEnd(&str);
! 5173: }
! 5174: }
! 5175:
! 5176: /*
! 5177: ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
! 5178: ** compresses it and sets (*ppOut) to point to a buffer containing the
! 5179: ** compressed data. The caller is responsible for eventually calling
! 5180: ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
! 5181: ** is set to the size of buffer (*ppOut) in bytes.
! 5182: **
! 5183: ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
! 5184: ** code is returned and an error message left in virtual-table handle
! 5185: ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
! 5186: ** case.
! 5187: */
! 5188: static int zipfileDeflate(
! 5189: const u8 *aIn, int nIn, /* Input */
! 5190: u8 **ppOut, int *pnOut, /* Output */
! 5191: char **pzErr /* OUT: Error message */
! 5192: ){
! 5193: sqlite3_int64 nAlloc = compressBound(nIn);
! 5194: u8 *aOut;
! 5195: int rc = SQLITE_OK;
! 5196:
! 5197: aOut = (u8*)sqlite3_malloc64(nAlloc);
! 5198: if( aOut==0 ){
! 5199: rc = SQLITE_NOMEM;
! 5200: }else{
! 5201: int res;
! 5202: z_stream str;
! 5203: memset(&str, 0, sizeof(str));
! 5204: str.next_in = (Bytef*)aIn;
! 5205: str.avail_in = nIn;
! 5206: str.next_out = aOut;
! 5207: str.avail_out = nAlloc;
! 5208:
! 5209: deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
! 5210: res = deflate(&str, Z_FINISH);
! 5211:
! 5212: if( res==Z_STREAM_END ){
! 5213: *ppOut = aOut;
! 5214: *pnOut = (int)str.total_out;
! 5215: }else{
! 5216: sqlite3_free(aOut);
! 5217: *pzErr = sqlite3_mprintf("zipfile: deflate() error");
! 5218: rc = SQLITE_ERROR;
! 5219: }
! 5220: deflateEnd(&str);
! 5221: }
! 5222:
! 5223: return rc;
! 5224: }
! 5225:
! 5226:
! 5227: /*
! 5228: ** Return values of columns for the row at which the series_cursor
! 5229: ** is currently pointing.
! 5230: */
! 5231: static int zipfileColumn(
! 5232: sqlite3_vtab_cursor *cur, /* The cursor */
! 5233: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 5234: int i /* Which column to return */
! 5235: ){
! 5236: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 5237: ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
! 5238: int rc = SQLITE_OK;
! 5239: switch( i ){
! 5240: case 0: /* name */
! 5241: sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
! 5242: break;
! 5243: case 1: /* mode */
! 5244: /* TODO: Whether or not the following is correct surely depends on
! 5245: ** the platform on which the archive was created. */
! 5246: sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
! 5247: break;
! 5248: case 2: { /* mtime */
! 5249: sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
! 5250: break;
! 5251: }
! 5252: case 3: { /* sz */
! 5253: if( sqlite3_vtab_nochange(ctx)==0 ){
! 5254: sqlite3_result_int64(ctx, pCDS->szUncompressed);
! 5255: }
! 5256: break;
! 5257: }
! 5258: case 4: /* rawdata */
! 5259: if( sqlite3_vtab_nochange(ctx) ) break;
! 5260: case 5: { /* data */
! 5261: if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
! 5262: int sz = pCDS->szCompressed;
! 5263: int szFinal = pCDS->szUncompressed;
! 5264: if( szFinal>0 ){
! 5265: u8 *aBuf;
! 5266: u8 *aFree = 0;
! 5267: if( pCsr->pCurrent->aData ){
! 5268: aBuf = pCsr->pCurrent->aData;
! 5269: }else{
! 5270: aBuf = aFree = sqlite3_malloc64(sz);
! 5271: if( aBuf==0 ){
! 5272: rc = SQLITE_NOMEM;
! 5273: }else{
! 5274: FILE *pFile = pCsr->pFile;
! 5275: if( pFile==0 ){
! 5276: pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
! 5277: }
! 5278: rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
! 5279: &pCsr->base.pVtab->zErrMsg
! 5280: );
! 5281: }
! 5282: }
! 5283: if( rc==SQLITE_OK ){
! 5284: if( i==5 && pCDS->iCompression ){
! 5285: zipfileInflate(ctx, aBuf, sz, szFinal);
! 5286: }else{
! 5287: sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
! 5288: }
! 5289: }
! 5290: sqlite3_free(aFree);
! 5291: }else{
! 5292: /* Figure out if this is a directory or a zero-sized file. Consider
! 5293: ** it to be a directory either if the mode suggests so, or if
! 5294: ** the final character in the name is '/'. */
! 5295: u32 mode = pCDS->iExternalAttr >> 16;
! 5296: if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
! 5297: sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
! 5298: }
! 5299: }
! 5300: }
! 5301: break;
! 5302: }
! 5303: case 6: /* method */
! 5304: sqlite3_result_int(ctx, pCDS->iCompression);
! 5305: break;
! 5306: default: /* z */
! 5307: assert( i==7 );
! 5308: sqlite3_result_int64(ctx, pCsr->iId);
! 5309: break;
! 5310: }
! 5311:
! 5312: return rc;
! 5313: }
! 5314:
! 5315: /*
! 5316: ** Return TRUE if the cursor is at EOF.
! 5317: */
! 5318: static int zipfileEof(sqlite3_vtab_cursor *cur){
! 5319: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 5320: return pCsr->bEof;
! 5321: }
! 5322:
! 5323: /*
! 5324: ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
! 5325: ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
! 5326: ** is guaranteed to be a file-handle open on a zip file.
! 5327: **
! 5328: ** This function attempts to locate the EOCD record within the zip archive
! 5329: ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
! 5330: ** returned if successful. Otherwise, an SQLite error code is returned and
! 5331: ** an English language error message may be left in virtual-table pTab.
! 5332: */
! 5333: static int zipfileReadEOCD(
! 5334: ZipfileTab *pTab, /* Return errors here */
! 5335: const u8 *aBlob, /* Pointer to in-memory file image */
! 5336: int nBlob, /* Size of aBlob[] in bytes */
! 5337: FILE *pFile, /* Read from this file if aBlob==0 */
! 5338: ZipfileEOCD *pEOCD /* Object to populate */
! 5339: ){
! 5340: u8 *aRead = pTab->aBuffer; /* Temporary buffer */
! 5341: int nRead; /* Bytes to read from file */
! 5342: int rc = SQLITE_OK;
! 5343:
! 5344: if( aBlob==0 ){
! 5345: i64 iOff; /* Offset to read from */
! 5346: i64 szFile; /* Total size of file in bytes */
! 5347: fseek(pFile, 0, SEEK_END);
! 5348: szFile = (i64)ftell(pFile);
! 5349: if( szFile==0 ){
! 5350: memset(pEOCD, 0, sizeof(ZipfileEOCD));
! 5351: return SQLITE_OK;
! 5352: }
! 5353: nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
! 5354: iOff = szFile - nRead;
! 5355: rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
! 5356: }else{
! 5357: nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
! 5358: aRead = (u8*)&aBlob[nBlob-nRead];
! 5359: }
! 5360:
! 5361: if( rc==SQLITE_OK ){
! 5362: int i;
! 5363:
! 5364: /* Scan backwards looking for the signature bytes */
! 5365: for(i=nRead-20; i>=0; i--){
! 5366: if( aRead[i]==0x50 && aRead[i+1]==0x4b
! 5367: && aRead[i+2]==0x05 && aRead[i+3]==0x06
! 5368: ){
! 5369: break;
! 5370: }
! 5371: }
! 5372: if( i<0 ){
! 5373: pTab->base.zErrMsg = sqlite3_mprintf(
! 5374: "cannot find end of central directory record"
! 5375: );
! 5376: return SQLITE_ERROR;
! 5377: }
! 5378:
! 5379: aRead += i+4;
! 5380: pEOCD->iDisk = zipfileRead16(aRead);
! 5381: pEOCD->iFirstDisk = zipfileRead16(aRead);
! 5382: pEOCD->nEntry = zipfileRead16(aRead);
! 5383: pEOCD->nEntryTotal = zipfileRead16(aRead);
! 5384: pEOCD->nSize = zipfileRead32(aRead);
! 5385: pEOCD->iOffset = zipfileRead32(aRead);
! 5386: }
! 5387:
! 5388: return rc;
! 5389: }
! 5390:
! 5391: /*
! 5392: ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
! 5393: ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
! 5394: ** to the end of the list. Otherwise, it is added to the list immediately
! 5395: ** before pBefore (which is guaranteed to be a part of said list).
! 5396: */
! 5397: static void zipfileAddEntry(
! 5398: ZipfileTab *pTab,
! 5399: ZipfileEntry *pBefore,
! 5400: ZipfileEntry *pNew
! 5401: ){
! 5402: assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
! 5403: assert( pNew->pNext==0 );
! 5404: if( pBefore==0 ){
! 5405: if( pTab->pFirstEntry==0 ){
! 5406: pTab->pFirstEntry = pTab->pLastEntry = pNew;
! 5407: }else{
! 5408: assert( pTab->pLastEntry->pNext==0 );
! 5409: pTab->pLastEntry->pNext = pNew;
! 5410: pTab->pLastEntry = pNew;
! 5411: }
! 5412: }else{
! 5413: ZipfileEntry **pp;
! 5414: for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
! 5415: pNew->pNext = pBefore;
! 5416: *pp = pNew;
! 5417: }
! 5418: }
! 5419:
! 5420: static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
! 5421: ZipfileEOCD eocd;
! 5422: int rc;
! 5423: int i;
! 5424: i64 iOff;
! 5425:
! 5426: rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
! 5427: iOff = eocd.iOffset;
! 5428: for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
! 5429: ZipfileEntry *pNew = 0;
! 5430: rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
! 5431:
! 5432: if( rc==SQLITE_OK ){
! 5433: zipfileAddEntry(pTab, 0, pNew);
! 5434: iOff += ZIPFILE_CDS_FIXED_SZ;
! 5435: iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
! 5436: }
! 5437: }
! 5438: return rc;
! 5439: }
! 5440:
! 5441: /*
! 5442: ** xFilter callback.
! 5443: */
! 5444: static int zipfileFilter(
! 5445: sqlite3_vtab_cursor *cur,
! 5446: int idxNum, const char *idxStr,
! 5447: int argc, sqlite3_value **argv
! 5448: ){
! 5449: ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
! 5450: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 5451: const char *zFile = 0; /* Zip file to scan */
! 5452: int rc = SQLITE_OK; /* Return Code */
! 5453: int bInMemory = 0; /* True for an in-memory zipfile */
! 5454:
! 5455: zipfileResetCursor(pCsr);
! 5456:
! 5457: if( pTab->zFile ){
! 5458: zFile = pTab->zFile;
! 5459: }else if( idxNum==0 ){
! 5460: zipfileCursorErr(pCsr, "zipfile() function requires an argument");
! 5461: return SQLITE_ERROR;
! 5462: }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
! 5463: const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
! 5464: int nBlob = sqlite3_value_bytes(argv[0]);
! 5465: assert( pTab->pFirstEntry==0 );
! 5466: rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
! 5467: pCsr->pFreeEntry = pTab->pFirstEntry;
! 5468: pTab->pFirstEntry = pTab->pLastEntry = 0;
! 5469: if( rc!=SQLITE_OK ) return rc;
! 5470: bInMemory = 1;
! 5471: }else{
! 5472: zFile = (const char*)sqlite3_value_text(argv[0]);
! 5473: }
! 5474:
! 5475: if( 0==pTab->pWriteFd && 0==bInMemory ){
! 5476: pCsr->pFile = fopen(zFile, "rb");
! 5477: if( pCsr->pFile==0 ){
! 5478: zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
! 5479: rc = SQLITE_ERROR;
! 5480: }else{
! 5481: rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
! 5482: if( rc==SQLITE_OK ){
! 5483: if( pCsr->eocd.nEntry==0 ){
! 5484: pCsr->bEof = 1;
! 5485: }else{
! 5486: pCsr->iNextOff = pCsr->eocd.iOffset;
! 5487: rc = zipfileNext(cur);
! 5488: }
! 5489: }
! 5490: }
! 5491: }else{
! 5492: pCsr->bNoop = 1;
! 5493: pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
! 5494: rc = zipfileNext(cur);
! 5495: }
! 5496:
! 5497: return rc;
! 5498: }
! 5499:
! 5500: /*
! 5501: ** xBestIndex callback.
! 5502: */
! 5503: static int zipfileBestIndex(
! 5504: sqlite3_vtab *tab,
! 5505: sqlite3_index_info *pIdxInfo
! 5506: ){
! 5507: int i;
! 5508: int idx = -1;
! 5509: int unusable = 0;
! 5510:
! 5511: for(i=0; i<pIdxInfo->nConstraint; i++){
! 5512: const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
! 5513: if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
! 5514: if( pCons->usable==0 ){
! 5515: unusable = 1;
! 5516: }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 5517: idx = i;
! 5518: }
! 5519: }
! 5520: if( idx>=0 ){
! 5521: pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
! 5522: pIdxInfo->aConstraintUsage[idx].omit = 1;
! 5523: pIdxInfo->estimatedCost = 1000.0;
! 5524: pIdxInfo->idxNum = 1;
! 5525: }else if( unusable ){
! 5526: return SQLITE_CONSTRAINT;
! 5527: }
! 5528: return SQLITE_OK;
! 5529: }
! 5530:
! 5531: static ZipfileEntry *zipfileNewEntry(const char *zPath){
! 5532: ZipfileEntry *pNew;
! 5533: pNew = sqlite3_malloc(sizeof(ZipfileEntry));
! 5534: if( pNew ){
! 5535: memset(pNew, 0, sizeof(ZipfileEntry));
! 5536: pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
! 5537: if( pNew->cds.zFile==0 ){
! 5538: sqlite3_free(pNew);
! 5539: pNew = 0;
! 5540: }
! 5541: }
! 5542: return pNew;
! 5543: }
! 5544:
! 5545: static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
! 5546: ZipfileCDS *pCds = &pEntry->cds;
! 5547: u8 *a = aBuf;
! 5548:
! 5549: pCds->nExtra = 9;
! 5550:
! 5551: /* Write the LFH itself */
! 5552: zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
! 5553: zipfileWrite16(a, pCds->iVersionExtract);
! 5554: zipfileWrite16(a, pCds->flags);
! 5555: zipfileWrite16(a, pCds->iCompression);
! 5556: zipfileWrite16(a, pCds->mTime);
! 5557: zipfileWrite16(a, pCds->mDate);
! 5558: zipfileWrite32(a, pCds->crc32);
! 5559: zipfileWrite32(a, pCds->szCompressed);
! 5560: zipfileWrite32(a, pCds->szUncompressed);
! 5561: zipfileWrite16(a, (u16)pCds->nFile);
! 5562: zipfileWrite16(a, pCds->nExtra);
! 5563: assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
! 5564:
! 5565: /* Add the file name */
! 5566: memcpy(a, pCds->zFile, (int)pCds->nFile);
! 5567: a += (int)pCds->nFile;
! 5568:
! 5569: /* The "extra" data */
! 5570: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
! 5571: zipfileWrite16(a, 5);
! 5572: *a++ = 0x01;
! 5573: zipfileWrite32(a, pEntry->mUnixTime);
! 5574:
! 5575: return a-aBuf;
! 5576: }
! 5577:
! 5578: static int zipfileAppendEntry(
! 5579: ZipfileTab *pTab,
! 5580: ZipfileEntry *pEntry,
! 5581: const u8 *pData,
! 5582: int nData
! 5583: ){
! 5584: u8 *aBuf = pTab->aBuffer;
! 5585: int nBuf;
! 5586: int rc;
! 5587:
! 5588: nBuf = zipfileSerializeLFH(pEntry, aBuf);
! 5589: rc = zipfileAppendData(pTab, aBuf, nBuf);
! 5590: if( rc==SQLITE_OK ){
! 5591: pEntry->iDataOff = pTab->szCurrent;
! 5592: rc = zipfileAppendData(pTab, pData, nData);
! 5593: }
! 5594:
! 5595: return rc;
! 5596: }
! 5597:
! 5598: static int zipfileGetMode(
! 5599: sqlite3_value *pVal,
! 5600: int bIsDir, /* If true, default to directory */
! 5601: u32 *pMode, /* OUT: Mode value */
! 5602: char **pzErr /* OUT: Error message */
! 5603: ){
! 5604: const char *z = (const char*)sqlite3_value_text(pVal);
! 5605: u32 mode = 0;
! 5606: if( z==0 ){
! 5607: mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
! 5608: }else if( z[0]>='0' && z[0]<='9' ){
! 5609: mode = (unsigned int)sqlite3_value_int(pVal);
! 5610: }else{
! 5611: const char zTemplate[11] = "-rwxrwxrwx";
! 5612: int i;
! 5613: if( strlen(z)!=10 ) goto parse_error;
! 5614: switch( z[0] ){
! 5615: case '-': mode |= S_IFREG; break;
! 5616: case 'd': mode |= S_IFDIR; break;
! 5617: case 'l': mode |= S_IFLNK; break;
! 5618: default: goto parse_error;
! 5619: }
! 5620: for(i=1; i<10; i++){
! 5621: if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
! 5622: else if( z[i]!='-' ) goto parse_error;
! 5623: }
! 5624: }
! 5625: if( ((mode & S_IFDIR)==0)==bIsDir ){
! 5626: /* The "mode" attribute is a directory, but data has been specified.
! 5627: ** Or vice-versa - no data but "mode" is a file or symlink. */
! 5628: *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
! 5629: return SQLITE_CONSTRAINT;
! 5630: }
! 5631: *pMode = mode;
! 5632: return SQLITE_OK;
! 5633:
! 5634: parse_error:
! 5635: *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
! 5636: return SQLITE_ERROR;
! 5637: }
! 5638:
! 5639: /*
! 5640: ** Both (const char*) arguments point to nul-terminated strings. Argument
! 5641: ** nB is the value of strlen(zB). This function returns 0 if the strings are
! 5642: ** identical, ignoring any trailing '/' character in either path. */
! 5643: static int zipfileComparePath(const char *zA, const char *zB, int nB){
! 5644: int nA = (int)strlen(zA);
! 5645: if( zA[nA-1]=='/' ) nA--;
! 5646: if( zB[nB-1]=='/' ) nB--;
! 5647: if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
! 5648: return 1;
! 5649: }
! 5650:
! 5651: static int zipfileBegin(sqlite3_vtab *pVtab){
! 5652: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 5653: int rc = SQLITE_OK;
! 5654:
! 5655: assert( pTab->pWriteFd==0 );
! 5656:
! 5657: /* Open a write fd on the file. Also load the entire central directory
! 5658: ** structure into memory. During the transaction any new file data is
! 5659: ** appended to the archive file, but the central directory is accumulated
! 5660: ** in main-memory until the transaction is committed. */
! 5661: pTab->pWriteFd = fopen(pTab->zFile, "ab+");
! 5662: if( pTab->pWriteFd==0 ){
! 5663: pTab->base.zErrMsg = sqlite3_mprintf(
! 5664: "zipfile: failed to open file %s for writing", pTab->zFile
! 5665: );
! 5666: rc = SQLITE_ERROR;
! 5667: }else{
! 5668: fseek(pTab->pWriteFd, 0, SEEK_END);
! 5669: pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
! 5670: rc = zipfileLoadDirectory(pTab, 0, 0);
! 5671: }
! 5672:
! 5673: if( rc!=SQLITE_OK ){
! 5674: zipfileCleanupTransaction(pTab);
! 5675: }
! 5676:
! 5677: return rc;
! 5678: }
! 5679:
! 5680: /*
! 5681: ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
! 5682: ** time(2)).
! 5683: */
! 5684: static u32 zipfileTime(void){
! 5685: sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
! 5686: u32 ret;
! 5687: if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
! 5688: i64 ms;
! 5689: pVfs->xCurrentTimeInt64(pVfs, &ms);
! 5690: ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
! 5691: }else{
! 5692: double day;
! 5693: pVfs->xCurrentTime(pVfs, &day);
! 5694: ret = (u32)((day - 2440587.5) * 86400);
! 5695: }
! 5696: return ret;
! 5697: }
! 5698:
! 5699: /*
! 5700: ** Return a 32-bit timestamp in UNIX epoch format.
! 5701: **
! 5702: ** If the value passed as the only argument is either NULL or an SQL NULL,
! 5703: ** return the current time. Otherwise, return the value stored in (*pVal)
! 5704: ** cast to a 32-bit unsigned integer.
! 5705: */
! 5706: static u32 zipfileGetTime(sqlite3_value *pVal){
! 5707: if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
! 5708: return zipfileTime();
! 5709: }
! 5710: return (u32)sqlite3_value_int64(pVal);
! 5711: }
! 5712:
! 5713: /*
! 5714: ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
! 5715: ** linked list. Remove it from the list and free the object.
! 5716: */
! 5717: static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
! 5718: if( pOld ){
! 5719: ZipfileEntry **pp;
! 5720: for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
! 5721: *pp = (*pp)->pNext;
! 5722: zipfileEntryFree(pOld);
! 5723: }
! 5724: }
! 5725:
! 5726: /*
! 5727: ** xUpdate method.
! 5728: */
! 5729: static int zipfileUpdate(
! 5730: sqlite3_vtab *pVtab,
! 5731: int nVal,
! 5732: sqlite3_value **apVal,
! 5733: sqlite_int64 *pRowid
! 5734: ){
! 5735: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 5736: int rc = SQLITE_OK; /* Return Code */
! 5737: ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
! 5738:
! 5739: u32 mode = 0; /* Mode for new entry */
! 5740: u32 mTime = 0; /* Modification time for new entry */
! 5741: i64 sz = 0; /* Uncompressed size */
! 5742: const char *zPath = 0; /* Path for new entry */
! 5743: int nPath = 0; /* strlen(zPath) */
! 5744: const u8 *pData = 0; /* Pointer to buffer containing content */
! 5745: int nData = 0; /* Size of pData buffer in bytes */
! 5746: int iMethod = 0; /* Compression method for new entry */
! 5747: u8 *pFree = 0; /* Free this */
! 5748: char *zFree = 0; /* Also free this */
! 5749: ZipfileEntry *pOld = 0;
! 5750: ZipfileEntry *pOld2 = 0;
! 5751: int bUpdate = 0; /* True for an update that modifies "name" */
! 5752: int bIsDir = 0;
! 5753: u32 iCrc32 = 0;
! 5754:
! 5755: if( pTab->pWriteFd==0 ){
! 5756: rc = zipfileBegin(pVtab);
! 5757: if( rc!=SQLITE_OK ) return rc;
! 5758: }
! 5759:
! 5760: /* If this is a DELETE or UPDATE, find the archive entry to delete. */
! 5761: if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
! 5762: const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
! 5763: int nDelete = (int)strlen(zDelete);
! 5764: if( nVal>1 ){
! 5765: const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
! 5766: if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
! 5767: bUpdate = 1;
! 5768: }
! 5769: }
! 5770: for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
! 5771: if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
! 5772: break;
! 5773: }
! 5774: assert( pOld->pNext );
! 5775: }
! 5776: }
! 5777:
! 5778: if( nVal>1 ){
! 5779: /* Check that "sz" and "rawdata" are both NULL: */
! 5780: if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
! 5781: zipfileTableErr(pTab, "sz must be NULL");
! 5782: rc = SQLITE_CONSTRAINT;
! 5783: }
! 5784: if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
! 5785: zipfileTableErr(pTab, "rawdata must be NULL");
! 5786: rc = SQLITE_CONSTRAINT;
! 5787: }
! 5788:
! 5789: if( rc==SQLITE_OK ){
! 5790: if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
! 5791: /* data=NULL. A directory */
! 5792: bIsDir = 1;
! 5793: }else{
! 5794: /* Value specified for "data", and possibly "method". This must be
! 5795: ** a regular file or a symlink. */
! 5796: const u8 *aIn = sqlite3_value_blob(apVal[7]);
! 5797: int nIn = sqlite3_value_bytes(apVal[7]);
! 5798: int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
! 5799:
! 5800: iMethod = sqlite3_value_int(apVal[8]);
! 5801: sz = nIn;
! 5802: pData = aIn;
! 5803: nData = nIn;
! 5804: if( iMethod!=0 && iMethod!=8 ){
! 5805: zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
! 5806: rc = SQLITE_CONSTRAINT;
! 5807: }else{
! 5808: if( bAuto || iMethod ){
! 5809: int nCmp;
! 5810: rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
! 5811: if( rc==SQLITE_OK ){
! 5812: if( iMethod || nCmp<nIn ){
! 5813: iMethod = 8;
! 5814: pData = pFree;
! 5815: nData = nCmp;
! 5816: }
! 5817: }
! 5818: }
! 5819: iCrc32 = crc32(0, aIn, nIn);
! 5820: }
! 5821: }
! 5822: }
! 5823:
! 5824: if( rc==SQLITE_OK ){
! 5825: rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
! 5826: }
! 5827:
! 5828: if( rc==SQLITE_OK ){
! 5829: zPath = (const char*)sqlite3_value_text(apVal[2]);
! 5830: nPath = (int)strlen(zPath);
! 5831: mTime = zipfileGetTime(apVal[4]);
! 5832: }
! 5833:
! 5834: if( rc==SQLITE_OK && bIsDir ){
! 5835: /* For a directory, check that the last character in the path is a
! 5836: ** '/'. This appears to be required for compatibility with info-zip
! 5837: ** (the unzip command on unix). It does not create directories
! 5838: ** otherwise. */
! 5839: if( zPath[nPath-1]!='/' ){
! 5840: zFree = sqlite3_mprintf("%s/", zPath);
! 5841: if( zFree==0 ){ rc = SQLITE_NOMEM; }
! 5842: zPath = (const char*)zFree;
! 5843: nPath++;
! 5844: }
! 5845: }
! 5846:
! 5847: /* Check that we're not inserting a duplicate entry -OR- updating an
! 5848: ** entry with a path, thereby making it into a duplicate. */
! 5849: if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
! 5850: ZipfileEntry *p;
! 5851: for(p=pTab->pFirstEntry; p; p=p->pNext){
! 5852: if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
! 5853: switch( sqlite3_vtab_on_conflict(pTab->db) ){
! 5854: case SQLITE_IGNORE: {
! 5855: goto zipfile_update_done;
! 5856: }
! 5857: case SQLITE_REPLACE: {
! 5858: pOld2 = p;
! 5859: break;
! 5860: }
! 5861: default: {
! 5862: zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
! 5863: rc = SQLITE_CONSTRAINT;
! 5864: break;
! 5865: }
! 5866: }
! 5867: break;
! 5868: }
! 5869: }
! 5870: }
! 5871:
! 5872: if( rc==SQLITE_OK ){
! 5873: /* Create the new CDS record. */
! 5874: pNew = zipfileNewEntry(zPath);
! 5875: if( pNew==0 ){
! 5876: rc = SQLITE_NOMEM;
! 5877: }else{
! 5878: pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
! 5879: pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
! 5880: pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
! 5881: pNew->cds.iCompression = (u16)iMethod;
! 5882: zipfileMtimeToDos(&pNew->cds, mTime);
! 5883: pNew->cds.crc32 = iCrc32;
! 5884: pNew->cds.szCompressed = nData;
! 5885: pNew->cds.szUncompressed = (u32)sz;
! 5886: pNew->cds.iExternalAttr = (mode<<16);
! 5887: pNew->cds.iOffset = (u32)pTab->szCurrent;
! 5888: pNew->cds.nFile = (u16)nPath;
! 5889: pNew->mUnixTime = (u32)mTime;
! 5890: rc = zipfileAppendEntry(pTab, pNew, pData, nData);
! 5891: zipfileAddEntry(pTab, pOld, pNew);
! 5892: }
! 5893: }
! 5894: }
! 5895:
! 5896: if( rc==SQLITE_OK && (pOld || pOld2) ){
! 5897: ZipfileCsr *pCsr;
! 5898: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
! 5899: if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
! 5900: pCsr->pCurrent = pCsr->pCurrent->pNext;
! 5901: pCsr->bNoop = 1;
! 5902: }
! 5903: }
! 5904:
! 5905: zipfileRemoveEntryFromList(pTab, pOld);
! 5906: zipfileRemoveEntryFromList(pTab, pOld2);
! 5907: }
! 5908:
! 5909: zipfile_update_done:
! 5910: sqlite3_free(pFree);
! 5911: sqlite3_free(zFree);
! 5912: return rc;
! 5913: }
! 5914:
! 5915: static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
! 5916: u8 *a = aBuf;
! 5917: zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
! 5918: zipfileWrite16(a, p->iDisk);
! 5919: zipfileWrite16(a, p->iFirstDisk);
! 5920: zipfileWrite16(a, p->nEntry);
! 5921: zipfileWrite16(a, p->nEntryTotal);
! 5922: zipfileWrite32(a, p->nSize);
! 5923: zipfileWrite32(a, p->iOffset);
! 5924: zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
! 5925:
! 5926: return a-aBuf;
! 5927: }
! 5928:
! 5929: static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
! 5930: int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
! 5931: assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
! 5932: return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
! 5933: }
! 5934:
! 5935: /*
! 5936: ** Serialize the CDS structure into buffer aBuf[]. Return the number
! 5937: ** of bytes written.
! 5938: */
! 5939: static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
! 5940: u8 *a = aBuf;
! 5941: ZipfileCDS *pCDS = &pEntry->cds;
! 5942:
! 5943: if( pEntry->aExtra==0 ){
! 5944: pCDS->nExtra = 9;
! 5945: }
! 5946:
! 5947: zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
! 5948: zipfileWrite16(a, pCDS->iVersionMadeBy);
! 5949: zipfileWrite16(a, pCDS->iVersionExtract);
! 5950: zipfileWrite16(a, pCDS->flags);
! 5951: zipfileWrite16(a, pCDS->iCompression);
! 5952: zipfileWrite16(a, pCDS->mTime);
! 5953: zipfileWrite16(a, pCDS->mDate);
! 5954: zipfileWrite32(a, pCDS->crc32);
! 5955: zipfileWrite32(a, pCDS->szCompressed);
! 5956: zipfileWrite32(a, pCDS->szUncompressed);
! 5957: assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
! 5958: zipfileWrite16(a, pCDS->nFile);
! 5959: zipfileWrite16(a, pCDS->nExtra);
! 5960: zipfileWrite16(a, pCDS->nComment);
! 5961: zipfileWrite16(a, pCDS->iDiskStart);
! 5962: zipfileWrite16(a, pCDS->iInternalAttr);
! 5963: zipfileWrite32(a, pCDS->iExternalAttr);
! 5964: zipfileWrite32(a, pCDS->iOffset);
! 5965:
! 5966: memcpy(a, pCDS->zFile, pCDS->nFile);
! 5967: a += pCDS->nFile;
! 5968:
! 5969: if( pEntry->aExtra ){
! 5970: int n = (int)pCDS->nExtra + (int)pCDS->nComment;
! 5971: memcpy(a, pEntry->aExtra, n);
! 5972: a += n;
! 5973: }else{
! 5974: assert( pCDS->nExtra==9 );
! 5975: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
! 5976: zipfileWrite16(a, 5);
! 5977: *a++ = 0x01;
! 5978: zipfileWrite32(a, pEntry->mUnixTime);
! 5979: }
! 5980:
! 5981: return a-aBuf;
! 5982: }
! 5983:
! 5984: static int zipfileCommit(sqlite3_vtab *pVtab){
! 5985: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 5986: int rc = SQLITE_OK;
! 5987: if( pTab->pWriteFd ){
! 5988: i64 iOffset = pTab->szCurrent;
! 5989: ZipfileEntry *p;
! 5990: ZipfileEOCD eocd;
! 5991: int nEntry = 0;
! 5992:
! 5993: /* Write out all entries */
! 5994: for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
! 5995: int n = zipfileSerializeCDS(p, pTab->aBuffer);
! 5996: rc = zipfileAppendData(pTab, pTab->aBuffer, n);
! 5997: nEntry++;
! 5998: }
! 5999:
! 6000: /* Write out the EOCD record */
! 6001: eocd.iDisk = 0;
! 6002: eocd.iFirstDisk = 0;
! 6003: eocd.nEntry = (u16)nEntry;
! 6004: eocd.nEntryTotal = (u16)nEntry;
! 6005: eocd.nSize = (u32)(pTab->szCurrent - iOffset);
! 6006: eocd.iOffset = (u32)iOffset;
! 6007: rc = zipfileAppendEOCD(pTab, &eocd);
! 6008:
! 6009: zipfileCleanupTransaction(pTab);
! 6010: }
! 6011: return rc;
! 6012: }
! 6013:
! 6014: static int zipfileRollback(sqlite3_vtab *pVtab){
! 6015: return zipfileCommit(pVtab);
! 6016: }
! 6017:
! 6018: static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
! 6019: ZipfileCsr *pCsr;
! 6020: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
! 6021: if( iId==pCsr->iId ) break;
! 6022: }
! 6023: return pCsr;
! 6024: }
! 6025:
! 6026: static void zipfileFunctionCds(
! 6027: sqlite3_context *context,
! 6028: int argc,
! 6029: sqlite3_value **argv
! 6030: ){
! 6031: ZipfileCsr *pCsr;
! 6032: ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
! 6033: assert( argc>0 );
! 6034:
! 6035: pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
! 6036: if( pCsr ){
! 6037: ZipfileCDS *p = &pCsr->pCurrent->cds;
! 6038: char *zRes = sqlite3_mprintf("{"
! 6039: "\"version-made-by\" : %u, "
! 6040: "\"version-to-extract\" : %u, "
! 6041: "\"flags\" : %u, "
! 6042: "\"compression\" : %u, "
! 6043: "\"time\" : %u, "
! 6044: "\"date\" : %u, "
! 6045: "\"crc32\" : %u, "
! 6046: "\"compressed-size\" : %u, "
! 6047: "\"uncompressed-size\" : %u, "
! 6048: "\"file-name-length\" : %u, "
! 6049: "\"extra-field-length\" : %u, "
! 6050: "\"file-comment-length\" : %u, "
! 6051: "\"disk-number-start\" : %u, "
! 6052: "\"internal-attr\" : %u, "
! 6053: "\"external-attr\" : %u, "
! 6054: "\"offset\" : %u }",
! 6055: (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
! 6056: (u32)p->flags, (u32)p->iCompression,
! 6057: (u32)p->mTime, (u32)p->mDate,
! 6058: (u32)p->crc32, (u32)p->szCompressed,
! 6059: (u32)p->szUncompressed, (u32)p->nFile,
! 6060: (u32)p->nExtra, (u32)p->nComment,
! 6061: (u32)p->iDiskStart, (u32)p->iInternalAttr,
! 6062: (u32)p->iExternalAttr, (u32)p->iOffset
! 6063: );
! 6064:
! 6065: if( zRes==0 ){
! 6066: sqlite3_result_error_nomem(context);
! 6067: }else{
! 6068: sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
! 6069: sqlite3_free(zRes);
! 6070: }
! 6071: }
! 6072: }
! 6073:
! 6074: /*
! 6075: ** xFindFunction method.
! 6076: */
! 6077: static int zipfileFindFunction(
! 6078: sqlite3_vtab *pVtab, /* Virtual table handle */
! 6079: int nArg, /* Number of SQL function arguments */
! 6080: const char *zName, /* Name of SQL function */
! 6081: void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
! 6082: void **ppArg /* OUT: User data for *pxFunc */
! 6083: ){
! 6084: if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
! 6085: *pxFunc = zipfileFunctionCds;
! 6086: *ppArg = (void*)pVtab;
! 6087: return 1;
! 6088: }
! 6089: return 0;
! 6090: }
! 6091:
! 6092: typedef struct ZipfileBuffer ZipfileBuffer;
! 6093: struct ZipfileBuffer {
! 6094: u8 *a; /* Pointer to buffer */
! 6095: int n; /* Size of buffer in bytes */
! 6096: int nAlloc; /* Byte allocated at a[] */
! 6097: };
! 6098:
! 6099: typedef struct ZipfileCtx ZipfileCtx;
! 6100: struct ZipfileCtx {
! 6101: int nEntry;
! 6102: ZipfileBuffer body;
! 6103: ZipfileBuffer cds;
! 6104: };
! 6105:
! 6106: static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
! 6107: if( pBuf->n+nByte>pBuf->nAlloc ){
! 6108: u8 *aNew;
! 6109: sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
! 6110: int nReq = pBuf->n + nByte;
! 6111:
! 6112: while( nNew<nReq ) nNew = nNew*2;
! 6113: aNew = sqlite3_realloc64(pBuf->a, nNew);
! 6114: if( aNew==0 ) return SQLITE_NOMEM;
! 6115: pBuf->a = aNew;
! 6116: pBuf->nAlloc = (int)nNew;
! 6117: }
! 6118: return SQLITE_OK;
! 6119: }
! 6120:
! 6121: /*
! 6122: ** xStep() callback for the zipfile() aggregate. This can be called in
! 6123: ** any of the following ways:
! 6124: **
! 6125: ** SELECT zipfile(name,data) ...
! 6126: ** SELECT zipfile(name,mode,mtime,data) ...
! 6127: ** SELECT zipfile(name,mode,mtime,data,method) ...
! 6128: */
! 6129: void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
! 6130: ZipfileCtx *p; /* Aggregate function context */
! 6131: ZipfileEntry e; /* New entry to add to zip archive */
! 6132:
! 6133: sqlite3_value *pName = 0;
! 6134: sqlite3_value *pMode = 0;
! 6135: sqlite3_value *pMtime = 0;
! 6136: sqlite3_value *pData = 0;
! 6137: sqlite3_value *pMethod = 0;
! 6138:
! 6139: int bIsDir = 0;
! 6140: u32 mode;
! 6141: int rc = SQLITE_OK;
! 6142: char *zErr = 0;
! 6143:
! 6144: int iMethod = -1; /* Compression method to use (0 or 8) */
! 6145:
! 6146: const u8 *aData = 0; /* Possibly compressed data for new entry */
! 6147: int nData = 0; /* Size of aData[] in bytes */
! 6148: int szUncompressed = 0; /* Size of data before compression */
! 6149: u8 *aFree = 0; /* Free this before returning */
! 6150: u32 iCrc32 = 0; /* crc32 of uncompressed data */
! 6151:
! 6152: char *zName = 0; /* Path (name) of new entry */
! 6153: int nName = 0; /* Size of zName in bytes */
! 6154: char *zFree = 0; /* Free this before returning */
! 6155: int nByte;
! 6156:
! 6157: memset(&e, 0, sizeof(e));
! 6158: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
! 6159: if( p==0 ) return;
! 6160:
! 6161: /* Martial the arguments into stack variables */
! 6162: if( nVal!=2 && nVal!=4 && nVal!=5 ){
! 6163: zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
! 6164: rc = SQLITE_ERROR;
! 6165: goto zipfile_step_out;
! 6166: }
! 6167: pName = apVal[0];
! 6168: if( nVal==2 ){
! 6169: pData = apVal[1];
! 6170: }else{
! 6171: pMode = apVal[1];
! 6172: pMtime = apVal[2];
! 6173: pData = apVal[3];
! 6174: if( nVal==5 ){
! 6175: pMethod = apVal[4];
! 6176: }
! 6177: }
! 6178:
! 6179: /* Check that the 'name' parameter looks ok. */
! 6180: zName = (char*)sqlite3_value_text(pName);
! 6181: nName = sqlite3_value_bytes(pName);
! 6182: if( zName==0 ){
! 6183: zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
! 6184: rc = SQLITE_ERROR;
! 6185: goto zipfile_step_out;
! 6186: }
! 6187:
! 6188: /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
! 6189: ** deflate compression) or NULL (choose automatically). */
! 6190: if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
! 6191: iMethod = (int)sqlite3_value_int64(pMethod);
! 6192: if( iMethod!=0 && iMethod!=8 ){
! 6193: zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
! 6194: rc = SQLITE_ERROR;
! 6195: goto zipfile_step_out;
! 6196: }
! 6197: }
! 6198:
! 6199: /* Now inspect the data. If this is NULL, then the new entry must be a
! 6200: ** directory. Otherwise, figure out whether or not the data should
! 6201: ** be deflated or simply stored in the zip archive. */
! 6202: if( sqlite3_value_type(pData)==SQLITE_NULL ){
! 6203: bIsDir = 1;
! 6204: iMethod = 0;
! 6205: }else{
! 6206: aData = sqlite3_value_blob(pData);
! 6207: szUncompressed = nData = sqlite3_value_bytes(pData);
! 6208: iCrc32 = crc32(0, aData, nData);
! 6209: if( iMethod<0 || iMethod==8 ){
! 6210: int nOut = 0;
! 6211: rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
! 6212: if( rc!=SQLITE_OK ){
! 6213: goto zipfile_step_out;
! 6214: }
! 6215: if( iMethod==8 || nOut<nData ){
! 6216: aData = aFree;
! 6217: nData = nOut;
! 6218: iMethod = 8;
! 6219: }else{
! 6220: iMethod = 0;
! 6221: }
! 6222: }
! 6223: }
! 6224:
! 6225: /* Decode the "mode" argument. */
! 6226: rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
! 6227: if( rc ) goto zipfile_step_out;
! 6228:
! 6229: /* Decode the "mtime" argument. */
! 6230: e.mUnixTime = zipfileGetTime(pMtime);
! 6231:
! 6232: /* If this is a directory entry, ensure that there is exactly one '/'
! 6233: ** at the end of the path. Or, if this is not a directory and the path
! 6234: ** ends in '/' it is an error. */
! 6235: if( bIsDir==0 ){
! 6236: if( zName[nName-1]=='/' ){
! 6237: zErr = sqlite3_mprintf("non-directory name must not end with /");
! 6238: rc = SQLITE_ERROR;
! 6239: goto zipfile_step_out;
! 6240: }
! 6241: }else{
! 6242: if( zName[nName-1]!='/' ){
! 6243: zName = zFree = sqlite3_mprintf("%s/", zName);
! 6244: nName++;
! 6245: if( zName==0 ){
! 6246: rc = SQLITE_NOMEM;
! 6247: goto zipfile_step_out;
! 6248: }
! 6249: }else{
! 6250: while( nName>1 && zName[nName-2]=='/' ) nName--;
! 6251: }
! 6252: }
! 6253:
! 6254: /* Assemble the ZipfileEntry object for the new zip archive entry */
! 6255: e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
! 6256: e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
! 6257: e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
! 6258: e.cds.iCompression = (u16)iMethod;
! 6259: zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
! 6260: e.cds.crc32 = iCrc32;
! 6261: e.cds.szCompressed = nData;
! 6262: e.cds.szUncompressed = szUncompressed;
! 6263: e.cds.iExternalAttr = (mode<<16);
! 6264: e.cds.iOffset = p->body.n;
! 6265: e.cds.nFile = (u16)nName;
! 6266: e.cds.zFile = zName;
! 6267:
! 6268: /* Append the LFH to the body of the new archive */
! 6269: nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
! 6270: if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
! 6271: p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
! 6272:
! 6273: /* Append the data to the body of the new archive */
! 6274: if( nData>0 ){
! 6275: if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
! 6276: memcpy(&p->body.a[p->body.n], aData, nData);
! 6277: p->body.n += nData;
! 6278: }
! 6279:
! 6280: /* Append the CDS record to the directory of the new archive */
! 6281: nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
! 6282: if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
! 6283: p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
! 6284:
! 6285: /* Increment the count of entries in the archive */
! 6286: p->nEntry++;
! 6287:
! 6288: zipfile_step_out:
! 6289: sqlite3_free(aFree);
! 6290: sqlite3_free(zFree);
! 6291: if( rc ){
! 6292: if( zErr ){
! 6293: sqlite3_result_error(pCtx, zErr, -1);
! 6294: }else{
! 6295: sqlite3_result_error_code(pCtx, rc);
! 6296: }
! 6297: }
! 6298: sqlite3_free(zErr);
! 6299: }
! 6300:
! 6301: /*
! 6302: ** xFinalize() callback for zipfile aggregate function.
! 6303: */
! 6304: void zipfileFinal(sqlite3_context *pCtx){
! 6305: ZipfileCtx *p;
! 6306: ZipfileEOCD eocd;
! 6307: sqlite3_int64 nZip;
! 6308: u8 *aZip;
! 6309:
! 6310: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
! 6311: if( p==0 ) return;
! 6312: if( p->nEntry>0 ){
! 6313: memset(&eocd, 0, sizeof(eocd));
! 6314: eocd.nEntry = (u16)p->nEntry;
! 6315: eocd.nEntryTotal = (u16)p->nEntry;
! 6316: eocd.nSize = p->cds.n;
! 6317: eocd.iOffset = p->body.n;
! 6318:
! 6319: nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
! 6320: aZip = (u8*)sqlite3_malloc64(nZip);
! 6321: if( aZip==0 ){
! 6322: sqlite3_result_error_nomem(pCtx);
! 6323: }else{
! 6324: memcpy(aZip, p->body.a, p->body.n);
! 6325: memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
! 6326: zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
! 6327: sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
! 6328: }
! 6329: }
! 6330:
! 6331: sqlite3_free(p->body.a);
! 6332: sqlite3_free(p->cds.a);
! 6333: }
! 6334:
! 6335:
! 6336: /*
! 6337: ** Register the "zipfile" virtual table.
! 6338: */
! 6339: static int zipfileRegister(sqlite3 *db){
! 6340: static sqlite3_module zipfileModule = {
! 6341: 1, /* iVersion */
! 6342: zipfileConnect, /* xCreate */
! 6343: zipfileConnect, /* xConnect */
! 6344: zipfileBestIndex, /* xBestIndex */
! 6345: zipfileDisconnect, /* xDisconnect */
! 6346: zipfileDisconnect, /* xDestroy */
! 6347: zipfileOpen, /* xOpen - open a cursor */
! 6348: zipfileClose, /* xClose - close a cursor */
! 6349: zipfileFilter, /* xFilter - configure scan constraints */
! 6350: zipfileNext, /* xNext - advance a cursor */
! 6351: zipfileEof, /* xEof - check for end of scan */
! 6352: zipfileColumn, /* xColumn - read data */
! 6353: 0, /* xRowid - read data */
! 6354: zipfileUpdate, /* xUpdate */
! 6355: zipfileBegin, /* xBegin */
! 6356: 0, /* xSync */
! 6357: zipfileCommit, /* xCommit */
! 6358: zipfileRollback, /* xRollback */
! 6359: zipfileFindFunction, /* xFindMethod */
! 6360: 0, /* xRename */
! 6361: };
! 6362:
! 6363: int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
! 6364: if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
! 6365: if( rc==SQLITE_OK ){
! 6366: rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
! 6367: zipfileStep, zipfileFinal
! 6368: );
! 6369: }
! 6370: return rc;
! 6371: }
! 6372: #else /* SQLITE_OMIT_VIRTUALTABLE */
! 6373: # define zipfileRegister(x) SQLITE_OK
! 6374: #endif
! 6375:
! 6376: #ifdef _WIN32
! 6377:
! 6378: #endif
! 6379: int sqlite3_zipfile_init(
! 6380: sqlite3 *db,
! 6381: char **pzErrMsg,
! 6382: const sqlite3_api_routines *pApi
! 6383: ){
! 6384: SQLITE_EXTENSION_INIT2(pApi);
! 6385: (void)pzErrMsg; /* Unused parameter */
! 6386: return zipfileRegister(db);
! 6387: }
! 6388:
! 6389: /************************* End ../ext/misc/zipfile.c ********************/
! 6390: /************************* Begin ../ext/misc/sqlar.c ******************/
! 6391: /*
! 6392: ** 2017-12-17
! 6393: **
! 6394: ** The author disclaims copyright to this source code. In place of
! 6395: ** a legal notice, here is a blessing:
! 6396: **
! 6397: ** May you do good and not evil.
! 6398: ** May you find forgiveness for yourself and forgive others.
! 6399: ** May you share freely, never taking more than you give.
! 6400: **
! 6401: ******************************************************************************
! 6402: **
! 6403: ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
! 6404: ** for working with sqlar archives and used by the shell tool's built-in
! 6405: ** sqlar support.
! 6406: */
! 6407: /* #include "sqlite3ext.h" */
! 6408: SQLITE_EXTENSION_INIT1
! 6409: #include <zlib.h>
! 6410:
! 6411: /*
! 6412: ** Implementation of the "sqlar_compress(X)" SQL function.
! 6413: **
! 6414: ** If the type of X is SQLITE_BLOB, and compressing that blob using
! 6415: ** zlib utility function compress() yields a smaller blob, return the
! 6416: ** compressed blob. Otherwise, return a copy of X.
! 6417: **
! 6418: ** SQLar uses the "zlib format" for compressed content. The zlib format
! 6419: ** contains a two-byte identification header and a four-byte checksum at
! 6420: ** the end. This is different from ZIP which uses the raw deflate format.
! 6421: **
! 6422: ** Future enhancements to SQLar might add support for new compression formats.
! 6423: ** If so, those new formats will be identified by alternative headers in the
! 6424: ** compressed data.
! 6425: */
! 6426: static void sqlarCompressFunc(
! 6427: sqlite3_context *context,
! 6428: int argc,
! 6429: sqlite3_value **argv
! 6430: ){
! 6431: assert( argc==1 );
! 6432: if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
! 6433: const Bytef *pData = sqlite3_value_blob(argv[0]);
! 6434: uLong nData = sqlite3_value_bytes(argv[0]);
! 6435: uLongf nOut = compressBound(nData);
! 6436: Bytef *pOut;
! 6437:
! 6438: pOut = (Bytef*)sqlite3_malloc(nOut);
! 6439: if( pOut==0 ){
! 6440: sqlite3_result_error_nomem(context);
! 6441: return;
! 6442: }else{
! 6443: if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
! 6444: sqlite3_result_error(context, "error in compress()", -1);
! 6445: }else if( nOut<nData ){
! 6446: sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
! 6447: }else{
! 6448: sqlite3_result_value(context, argv[0]);
! 6449: }
! 6450: sqlite3_free(pOut);
! 6451: }
! 6452: }else{
! 6453: sqlite3_result_value(context, argv[0]);
! 6454: }
! 6455: }
! 6456:
! 6457: /*
! 6458: ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
! 6459: **
! 6460: ** Parameter SZ is interpreted as an integer. If it is less than or
! 6461: ** equal to zero, then this function returns a copy of X. Or, if
! 6462: ** SZ is equal to the size of X when interpreted as a blob, also
! 6463: ** return a copy of X. Otherwise, decompress blob X using zlib
! 6464: ** utility function uncompress() and return the results (another
! 6465: ** blob).
! 6466: */
! 6467: static void sqlarUncompressFunc(
! 6468: sqlite3_context *context,
! 6469: int argc,
! 6470: sqlite3_value **argv
! 6471: ){
! 6472: uLong nData;
! 6473: uLongf sz;
! 6474:
! 6475: assert( argc==2 );
! 6476: sz = sqlite3_value_int(argv[1]);
! 6477:
! 6478: if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
! 6479: sqlite3_result_value(context, argv[0]);
! 6480: }else{
! 6481: const Bytef *pData= sqlite3_value_blob(argv[0]);
! 6482: Bytef *pOut = sqlite3_malloc(sz);
! 6483: if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
! 6484: sqlite3_result_error(context, "error in uncompress()", -1);
! 6485: }else{
! 6486: sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
! 6487: }
! 6488: sqlite3_free(pOut);
! 6489: }
! 6490: }
! 6491:
! 6492:
! 6493: #ifdef _WIN32
! 6494:
! 6495: #endif
! 6496: int sqlite3_sqlar_init(
! 6497: sqlite3 *db,
! 6498: char **pzErrMsg,
! 6499: const sqlite3_api_routines *pApi
! 6500: ){
! 6501: int rc = SQLITE_OK;
! 6502: SQLITE_EXTENSION_INIT2(pApi);
! 6503: (void)pzErrMsg; /* Unused parameter */
! 6504: rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
! 6505: sqlarCompressFunc, 0, 0);
! 6506: if( rc==SQLITE_OK ){
! 6507: rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
! 6508: sqlarUncompressFunc, 0, 0);
! 6509: }
! 6510: return rc;
! 6511: }
! 6512:
! 6513: /************************* End ../ext/misc/sqlar.c ********************/
! 6514: #endif
! 6515: /************************* Begin ../ext/expert/sqlite3expert.h ******************/
! 6516: /*
! 6517: ** 2017 April 07
! 6518: **
! 6519: ** The author disclaims copyright to this source code. In place of
! 6520: ** a legal notice, here is a blessing:
! 6521: **
! 6522: ** May you do good and not evil.
! 6523: ** May you find forgiveness for yourself and forgive others.
! 6524: ** May you share freely, never taking more than you give.
! 6525: **
! 6526: *************************************************************************
! 6527: */
! 6528:
! 6529:
! 6530: /* #include "sqlite3.h" */
! 6531:
! 6532: typedef struct sqlite3expert sqlite3expert;
! 6533:
! 6534: /*
! 6535: ** Create a new sqlite3expert object.
! 6536: **
! 6537: ** If successful, a pointer to the new object is returned and (*pzErr) set
! 6538: ** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
! 6539: ** an English-language error message. In this case it is the responsibility
! 6540: ** of the caller to eventually free the error message buffer using
! 6541: ** sqlite3_free().
! 6542: */
! 6543: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
! 6544:
! 6545: /*
! 6546: ** Configure an sqlite3expert object.
! 6547: **
! 6548: ** EXPERT_CONFIG_SAMPLE:
! 6549: ** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
! 6550: ** each candidate index. This involves scanning and sorting the entire
! 6551: ** contents of each user database table once for each candidate index
! 6552: ** associated with the table. For large databases, this can be
! 6553: ** prohibitively slow. This option allows the sqlite3expert object to
! 6554: ** be configured so that sqlite_stat1 data is instead generated based on a
! 6555: ** subset of each table, or so that no sqlite_stat1 data is used at all.
! 6556: **
! 6557: ** A single integer argument is passed to this option. If the value is less
! 6558: ** than or equal to zero, then no sqlite_stat1 data is generated or used by
! 6559: ** the analysis - indexes are recommended based on the database schema only.
! 6560: ** Or, if the value is 100 or greater, complete sqlite_stat1 data is
! 6561: ** generated for each candidate index (this is the default). Finally, if the
! 6562: ** value falls between 0 and 100, then it represents the percentage of user
! 6563: ** table rows that should be considered when generating sqlite_stat1 data.
! 6564: **
! 6565: ** Examples:
! 6566: **
! 6567: ** // Do not generate any sqlite_stat1 data
! 6568: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
! 6569: **
! 6570: ** // Generate sqlite_stat1 data based on 10% of the rows in each table.
! 6571: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
! 6572: */
! 6573: int sqlite3_expert_config(sqlite3expert *p, int op, ...);
! 6574:
! 6575: #define EXPERT_CONFIG_SAMPLE 1 /* int */
! 6576:
! 6577: /*
! 6578: ** Specify zero or more SQL statements to be included in the analysis.
! 6579: **
! 6580: ** Buffer zSql must contain zero or more complete SQL statements. This
! 6581: ** function parses all statements contained in the buffer and adds them
! 6582: ** to the internal list of statements to analyze. If successful, SQLITE_OK
! 6583: ** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
! 6584: ** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
! 6585: ** may be set to point to an English language error message. In this case
! 6586: ** the caller is responsible for eventually freeing the error message buffer
! 6587: ** using sqlite3_free().
! 6588: **
! 6589: ** If an error does occur while processing one of the statements in the
! 6590: ** buffer passed as the second argument, none of the statements in the
! 6591: ** buffer are added to the analysis.
! 6592: **
! 6593: ** This function must be called before sqlite3_expert_analyze(). If a call
! 6594: ** to this function is made on an sqlite3expert object that has already
! 6595: ** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
! 6596: ** immediately and no statements are added to the analysis.
! 6597: */
! 6598: int sqlite3_expert_sql(
! 6599: sqlite3expert *p, /* From a successful sqlite3_expert_new() */
! 6600: const char *zSql, /* SQL statement(s) to add */
! 6601: char **pzErr /* OUT: Error message (if any) */
! 6602: );
! 6603:
! 6604:
! 6605: /*
! 6606: ** This function is called after the sqlite3expert object has been configured
! 6607: ** with all SQL statements using sqlite3_expert_sql() to actually perform
! 6608: ** the analysis. Once this function has been called, it is not possible to
! 6609: ** add further SQL statements to the analysis.
! 6610: **
! 6611: ** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
! 6612: ** an error occurs, an SQLite error code is returned and (*pzErr) set to
! 6613: ** point to a buffer containing an English language error message. In this
! 6614: ** case it is the responsibility of the caller to eventually free the buffer
! 6615: ** using sqlite3_free().
! 6616: **
! 6617: ** If an error does occur within this function, the sqlite3expert object
! 6618: ** is no longer useful for any purpose. At that point it is no longer
! 6619: ** possible to add further SQL statements to the object or to re-attempt
! 6620: ** the analysis. The sqlite3expert object must still be freed using a call
! 6621: ** sqlite3_expert_destroy().
! 6622: */
! 6623: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
! 6624:
! 6625: /*
! 6626: ** Return the total number of statements loaded using sqlite3_expert_sql().
! 6627: ** The total number of SQL statements may be different from the total number
! 6628: ** to calls to sqlite3_expert_sql().
! 6629: */
! 6630: int sqlite3_expert_count(sqlite3expert*);
! 6631:
! 6632: /*
! 6633: ** Return a component of the report.
! 6634: **
! 6635: ** This function is called after sqlite3_expert_analyze() to extract the
! 6636: ** results of the analysis. Each call to this function returns either a
! 6637: ** NULL pointer or a pointer to a buffer containing a nul-terminated string.
! 6638: ** The value passed as the third argument must be one of the EXPERT_REPORT_*
! 6639: ** #define constants defined below.
! 6640: **
! 6641: ** For some EXPERT_REPORT_* parameters, the buffer returned contains
! 6642: ** information relating to a specific SQL statement. In these cases that
! 6643: ** SQL statement is identified by the value passed as the second argument.
! 6644: ** SQL statements are numbered from 0 in the order in which they are parsed.
! 6645: ** If an out-of-range value (less than zero or equal to or greater than the
! 6646: ** value returned by sqlite3_expert_count()) is passed as the second argument
! 6647: ** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
! 6648: **
! 6649: ** EXPERT_REPORT_SQL:
! 6650: ** Return the text of SQL statement iStmt.
! 6651: **
! 6652: ** EXPERT_REPORT_INDEXES:
! 6653: ** Return a buffer containing the CREATE INDEX statements for all recommended
! 6654: ** indexes for statement iStmt. If there are no new recommeded indexes, NULL
! 6655: ** is returned.
! 6656: **
! 6657: ** EXPERT_REPORT_PLAN:
! 6658: ** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
! 6659: ** iStmt after the proposed indexes have been added to the database schema.
! 6660: **
! 6661: ** EXPERT_REPORT_CANDIDATES:
! 6662: ** Return a pointer to a buffer containing the CREATE INDEX statements
! 6663: ** for all indexes that were tested (for all SQL statements). The iStmt
! 6664: ** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
! 6665: */
! 6666: const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
! 6667:
! 6668: /*
! 6669: ** Values for the third argument passed to sqlite3_expert_report().
! 6670: */
! 6671: #define EXPERT_REPORT_SQL 1
! 6672: #define EXPERT_REPORT_INDEXES 2
! 6673: #define EXPERT_REPORT_PLAN 3
! 6674: #define EXPERT_REPORT_CANDIDATES 4
! 6675:
! 6676: /*
! 6677: ** Free an (sqlite3expert*) handle and all associated resources. There
! 6678: ** should be one call to this function for each successful call to
! 6679: ** sqlite3-expert_new().
! 6680: */
! 6681: void sqlite3_expert_destroy(sqlite3expert*);
! 6682:
! 6683:
! 6684:
! 6685: /************************* End ../ext/expert/sqlite3expert.h ********************/
! 6686: /************************* Begin ../ext/expert/sqlite3expert.c ******************/
! 6687: /*
! 6688: ** 2017 April 09
! 6689: **
! 6690: ** The author disclaims copyright to this source code. In place of
! 6691: ** a legal notice, here is a blessing:
! 6692: **
! 6693: ** May you do good and not evil.
! 6694: ** May you find forgiveness for yourself and forgive others.
! 6695: ** May you share freely, never taking more than you give.
! 6696: **
! 6697: *************************************************************************
! 6698: */
! 6699: /* #include "sqlite3expert.h" */
! 6700: #include <assert.h>
! 6701: #include <string.h>
! 6702: #include <stdio.h>
! 6703:
! 6704: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 6705:
! 6706: /* typedef sqlite3_int64 i64; */
! 6707: /* typedef sqlite3_uint64 u64; */
! 6708:
! 6709: typedef struct IdxColumn IdxColumn;
! 6710: typedef struct IdxConstraint IdxConstraint;
! 6711: typedef struct IdxScan IdxScan;
! 6712: typedef struct IdxStatement IdxStatement;
! 6713: typedef struct IdxTable IdxTable;
! 6714: typedef struct IdxWrite IdxWrite;
! 6715:
! 6716: #define STRLEN (int)strlen
! 6717:
! 6718: /*
! 6719: ** A temp table name that we assume no user database will actually use.
! 6720: ** If this assumption proves incorrect triggers on the table with the
! 6721: ** conflicting name will be ignored.
! 6722: */
! 6723: #define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
! 6724:
! 6725: /*
! 6726: ** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
! 6727: ** any other type of single-ended range constraint on a column).
! 6728: **
! 6729: ** pLink:
! 6730: ** Used to temporarily link IdxConstraint objects into lists while
! 6731: ** creating candidate indexes.
! 6732: */
! 6733: struct IdxConstraint {
! 6734: char *zColl; /* Collation sequence */
! 6735: int bRange; /* True for range, false for eq */
! 6736: int iCol; /* Constrained table column */
! 6737: int bFlag; /* Used by idxFindCompatible() */
! 6738: int bDesc; /* True if ORDER BY <expr> DESC */
! 6739: IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
! 6740: IdxConstraint *pLink; /* See above */
! 6741: };
! 6742:
! 6743: /*
! 6744: ** A single scan of a single table.
! 6745: */
! 6746: struct IdxScan {
! 6747: IdxTable *pTab; /* Associated table object */
! 6748: int iDb; /* Database containing table zTable */
! 6749: i64 covering; /* Mask of columns required for cov. index */
! 6750: IdxConstraint *pOrder; /* ORDER BY columns */
! 6751: IdxConstraint *pEq; /* List of == constraints */
! 6752: IdxConstraint *pRange; /* List of < constraints */
! 6753: IdxScan *pNextScan; /* Next IdxScan object for same analysis */
! 6754: };
! 6755:
! 6756: /*
! 6757: ** Information regarding a single database table. Extracted from
! 6758: ** "PRAGMA table_info" by function idxGetTableInfo().
! 6759: */
! 6760: struct IdxColumn {
! 6761: char *zName;
! 6762: char *zColl;
! 6763: int iPk;
! 6764: };
! 6765: struct IdxTable {
! 6766: int nCol;
! 6767: char *zName; /* Table name */
! 6768: IdxColumn *aCol;
! 6769: IdxTable *pNext; /* Next table in linked list of all tables */
! 6770: };
! 6771:
! 6772: /*
! 6773: ** An object of the following type is created for each unique table/write-op
! 6774: ** seen. The objects are stored in a singly-linked list beginning at
! 6775: ** sqlite3expert.pWrite.
! 6776: */
! 6777: struct IdxWrite {
! 6778: IdxTable *pTab;
! 6779: int eOp; /* SQLITE_UPDATE, DELETE or INSERT */
! 6780: IdxWrite *pNext;
! 6781: };
! 6782:
! 6783: /*
! 6784: ** Each statement being analyzed is represented by an instance of this
! 6785: ** structure.
! 6786: */
! 6787: struct IdxStatement {
! 6788: int iId; /* Statement number */
! 6789: char *zSql; /* SQL statement */
! 6790: char *zIdx; /* Indexes */
! 6791: char *zEQP; /* Plan */
! 6792: IdxStatement *pNext;
! 6793: };
! 6794:
! 6795:
! 6796: /*
! 6797: ** A hash table for storing strings. With space for a payload string
! 6798: ** with each entry. Methods are:
! 6799: **
! 6800: ** idxHashInit()
! 6801: ** idxHashClear()
! 6802: ** idxHashAdd()
! 6803: ** idxHashSearch()
! 6804: */
! 6805: #define IDX_HASH_SIZE 1023
! 6806: typedef struct IdxHashEntry IdxHashEntry;
! 6807: typedef struct IdxHash IdxHash;
! 6808: struct IdxHashEntry {
! 6809: char *zKey; /* nul-terminated key */
! 6810: char *zVal; /* nul-terminated value string */
! 6811: char *zVal2; /* nul-terminated value string 2 */
! 6812: IdxHashEntry *pHashNext; /* Next entry in same hash bucket */
! 6813: IdxHashEntry *pNext; /* Next entry in hash */
! 6814: };
! 6815: struct IdxHash {
! 6816: IdxHashEntry *pFirst;
! 6817: IdxHashEntry *aHash[IDX_HASH_SIZE];
! 6818: };
! 6819:
! 6820: /*
! 6821: ** sqlite3expert object.
! 6822: */
! 6823: struct sqlite3expert {
! 6824: int iSample; /* Percentage of tables to sample for stat1 */
! 6825: sqlite3 *db; /* User database */
! 6826: sqlite3 *dbm; /* In-memory db for this analysis */
! 6827: sqlite3 *dbv; /* Vtab schema for this analysis */
! 6828: IdxTable *pTable; /* List of all IdxTable objects */
! 6829: IdxScan *pScan; /* List of scan objects */
! 6830: IdxWrite *pWrite; /* List of write objects */
! 6831: IdxStatement *pStatement; /* List of IdxStatement objects */
! 6832: int bRun; /* True once analysis has run */
! 6833: char **pzErrmsg;
! 6834: int rc; /* Error code from whereinfo hook */
! 6835: IdxHash hIdx; /* Hash containing all candidate indexes */
! 6836: char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
! 6837: };
! 6838:
! 6839:
! 6840: /*
! 6841: ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
! 6842: ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
! 6843: */
! 6844: static void *idxMalloc(int *pRc, int nByte){
! 6845: void *pRet;
! 6846: assert( *pRc==SQLITE_OK );
! 6847: assert( nByte>0 );
! 6848: pRet = sqlite3_malloc(nByte);
! 6849: if( pRet ){
! 6850: memset(pRet, 0, nByte);
! 6851: }else{
! 6852: *pRc = SQLITE_NOMEM;
! 6853: }
! 6854: return pRet;
! 6855: }
! 6856:
! 6857: /*
! 6858: ** Initialize an IdxHash hash table.
! 6859: */
! 6860: static void idxHashInit(IdxHash *pHash){
! 6861: memset(pHash, 0, sizeof(IdxHash));
! 6862: }
! 6863:
! 6864: /*
! 6865: ** Reset an IdxHash hash table.
! 6866: */
! 6867: static void idxHashClear(IdxHash *pHash){
! 6868: int i;
! 6869: for(i=0; i<IDX_HASH_SIZE; i++){
! 6870: IdxHashEntry *pEntry;
! 6871: IdxHashEntry *pNext;
! 6872: for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
! 6873: pNext = pEntry->pHashNext;
! 6874: sqlite3_free(pEntry->zVal2);
! 6875: sqlite3_free(pEntry);
! 6876: }
! 6877: }
! 6878: memset(pHash, 0, sizeof(IdxHash));
! 6879: }
! 6880:
! 6881: /*
! 6882: ** Return the index of the hash bucket that the string specified by the
! 6883: ** arguments to this function belongs.
! 6884: */
! 6885: static int idxHashString(const char *z, int n){
! 6886: unsigned int ret = 0;
! 6887: int i;
! 6888: for(i=0; i<n; i++){
! 6889: ret += (ret<<3) + (unsigned char)(z[i]);
! 6890: }
! 6891: return (int)(ret % IDX_HASH_SIZE);
! 6892: }
! 6893:
! 6894: /*
! 6895: ** If zKey is already present in the hash table, return non-zero and do
! 6896: ** nothing. Otherwise, add an entry with key zKey and payload string zVal to
! 6897: ** the hash table passed as the second argument.
! 6898: */
! 6899: static int idxHashAdd(
! 6900: int *pRc,
! 6901: IdxHash *pHash,
! 6902: const char *zKey,
! 6903: const char *zVal
! 6904: ){
! 6905: int nKey = STRLEN(zKey);
! 6906: int iHash = idxHashString(zKey, nKey);
! 6907: int nVal = (zVal ? STRLEN(zVal) : 0);
! 6908: IdxHashEntry *pEntry;
! 6909: assert( iHash>=0 );
! 6910: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
! 6911: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
! 6912: return 1;
! 6913: }
! 6914: }
! 6915: pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
! 6916: if( pEntry ){
! 6917: pEntry->zKey = (char*)&pEntry[1];
! 6918: memcpy(pEntry->zKey, zKey, nKey);
! 6919: if( zVal ){
! 6920: pEntry->zVal = &pEntry->zKey[nKey+1];
! 6921: memcpy(pEntry->zVal, zVal, nVal);
! 6922: }
! 6923: pEntry->pHashNext = pHash->aHash[iHash];
! 6924: pHash->aHash[iHash] = pEntry;
! 6925:
! 6926: pEntry->pNext = pHash->pFirst;
! 6927: pHash->pFirst = pEntry;
! 6928: }
! 6929: return 0;
! 6930: }
! 6931:
! 6932: /*
! 6933: ** If zKey/nKey is present in the hash table, return a pointer to the
! 6934: ** hash-entry object.
! 6935: */
! 6936: static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
! 6937: int iHash;
! 6938: IdxHashEntry *pEntry;
! 6939: if( nKey<0 ) nKey = STRLEN(zKey);
! 6940: iHash = idxHashString(zKey, nKey);
! 6941: assert( iHash>=0 );
! 6942: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
! 6943: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
! 6944: return pEntry;
! 6945: }
! 6946: }
! 6947: return 0;
! 6948: }
! 6949:
! 6950: /*
! 6951: ** If the hash table contains an entry with a key equal to the string
! 6952: ** passed as the final two arguments to this function, return a pointer
! 6953: ** to the payload string. Otherwise, if zKey/nKey is not present in the
! 6954: ** hash table, return NULL.
! 6955: */
! 6956: static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
! 6957: IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
! 6958: if( pEntry ) return pEntry->zVal;
! 6959: return 0;
! 6960: }
! 6961:
! 6962: /*
! 6963: ** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
! 6964: ** variable to point to a copy of nul-terminated string zColl.
! 6965: */
! 6966: static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
! 6967: IdxConstraint *pNew;
! 6968: int nColl = STRLEN(zColl);
! 6969:
! 6970: assert( *pRc==SQLITE_OK );
! 6971: pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
! 6972: if( pNew ){
! 6973: pNew->zColl = (char*)&pNew[1];
! 6974: memcpy(pNew->zColl, zColl, nColl+1);
! 6975: }
! 6976: return pNew;
! 6977: }
! 6978:
! 6979: /*
! 6980: ** An error associated with database handle db has just occurred. Pass
! 6981: ** the error message to callback function xOut.
! 6982: */
! 6983: static void idxDatabaseError(
! 6984: sqlite3 *db, /* Database handle */
! 6985: char **pzErrmsg /* Write error here */
! 6986: ){
! 6987: *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
! 6988: }
! 6989:
! 6990: /*
! 6991: ** Prepare an SQL statement.
! 6992: */
! 6993: static int idxPrepareStmt(
! 6994: sqlite3 *db, /* Database handle to compile against */
! 6995: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
! 6996: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
! 6997: const char *zSql /* SQL statement to compile */
! 6998: ){
! 6999: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
! 7000: if( rc!=SQLITE_OK ){
! 7001: *ppStmt = 0;
! 7002: idxDatabaseError(db, pzErrmsg);
! 7003: }
! 7004: return rc;
! 7005: }
! 7006:
! 7007: /*
! 7008: ** Prepare an SQL statement using the results of a printf() formatting.
! 7009: */
! 7010: static int idxPrintfPrepareStmt(
! 7011: sqlite3 *db, /* Database handle to compile against */
! 7012: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
! 7013: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
! 7014: const char *zFmt, /* printf() format of SQL statement */
! 7015: ... /* Trailing printf() arguments */
! 7016: ){
! 7017: va_list ap;
! 7018: int rc;
! 7019: char *zSql;
! 7020: va_start(ap, zFmt);
! 7021: zSql = sqlite3_vmprintf(zFmt, ap);
! 7022: if( zSql==0 ){
! 7023: rc = SQLITE_NOMEM;
! 7024: }else{
! 7025: rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
! 7026: sqlite3_free(zSql);
! 7027: }
! 7028: va_end(ap);
! 7029: return rc;
! 7030: }
! 7031:
! 7032:
! 7033: /*************************************************************************
! 7034: ** Beginning of virtual table implementation.
! 7035: */
! 7036: typedef struct ExpertVtab ExpertVtab;
! 7037: struct ExpertVtab {
! 7038: sqlite3_vtab base;
! 7039: IdxTable *pTab;
! 7040: sqlite3expert *pExpert;
! 7041: };
! 7042:
! 7043: typedef struct ExpertCsr ExpertCsr;
! 7044: struct ExpertCsr {
! 7045: sqlite3_vtab_cursor base;
! 7046: sqlite3_stmt *pData;
! 7047: };
! 7048:
! 7049: static char *expertDequote(const char *zIn){
! 7050: int n = STRLEN(zIn);
! 7051: char *zRet = sqlite3_malloc(n);
! 7052:
! 7053: assert( zIn[0]=='\'' );
! 7054: assert( zIn[n-1]=='\'' );
! 7055:
! 7056: if( zRet ){
! 7057: int iOut = 0;
! 7058: int iIn = 0;
! 7059: for(iIn=1; iIn<(n-1); iIn++){
! 7060: if( zIn[iIn]=='\'' ){
! 7061: assert( zIn[iIn+1]=='\'' );
! 7062: iIn++;
! 7063: }
! 7064: zRet[iOut++] = zIn[iIn];
! 7065: }
! 7066: zRet[iOut] = '\0';
! 7067: }
! 7068:
! 7069: return zRet;
! 7070: }
! 7071:
! 7072: /*
! 7073: ** This function is the implementation of both the xConnect and xCreate
! 7074: ** methods of the r-tree virtual table.
! 7075: **
! 7076: ** argv[0] -> module name
! 7077: ** argv[1] -> database name
! 7078: ** argv[2] -> table name
! 7079: ** argv[...] -> column names...
! 7080: */
! 7081: static int expertConnect(
! 7082: sqlite3 *db,
! 7083: void *pAux,
! 7084: int argc, const char *const*argv,
! 7085: sqlite3_vtab **ppVtab,
! 7086: char **pzErr
! 7087: ){
! 7088: sqlite3expert *pExpert = (sqlite3expert*)pAux;
! 7089: ExpertVtab *p = 0;
! 7090: int rc;
! 7091:
! 7092: if( argc!=4 ){
! 7093: *pzErr = sqlite3_mprintf("internal error!");
! 7094: rc = SQLITE_ERROR;
! 7095: }else{
! 7096: char *zCreateTable = expertDequote(argv[3]);
! 7097: if( zCreateTable ){
! 7098: rc = sqlite3_declare_vtab(db, zCreateTable);
! 7099: if( rc==SQLITE_OK ){
! 7100: p = idxMalloc(&rc, sizeof(ExpertVtab));
! 7101: }
! 7102: if( rc==SQLITE_OK ){
! 7103: p->pExpert = pExpert;
! 7104: p->pTab = pExpert->pTable;
! 7105: assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
! 7106: }
! 7107: sqlite3_free(zCreateTable);
! 7108: }else{
! 7109: rc = SQLITE_NOMEM;
! 7110: }
! 7111: }
! 7112:
! 7113: *ppVtab = (sqlite3_vtab*)p;
! 7114: return rc;
! 7115: }
! 7116:
! 7117: static int expertDisconnect(sqlite3_vtab *pVtab){
! 7118: ExpertVtab *p = (ExpertVtab*)pVtab;
! 7119: sqlite3_free(p);
! 7120: return SQLITE_OK;
! 7121: }
! 7122:
! 7123: static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
! 7124: ExpertVtab *p = (ExpertVtab*)pVtab;
! 7125: int rc = SQLITE_OK;
! 7126: int n = 0;
! 7127: IdxScan *pScan;
! 7128: const int opmask =
! 7129: SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
! 7130: SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
! 7131: SQLITE_INDEX_CONSTRAINT_LE;
! 7132:
! 7133: pScan = idxMalloc(&rc, sizeof(IdxScan));
! 7134: if( pScan ){
! 7135: int i;
! 7136:
! 7137: /* Link the new scan object into the list */
! 7138: pScan->pTab = p->pTab;
! 7139: pScan->pNextScan = p->pExpert->pScan;
! 7140: p->pExpert->pScan = pScan;
! 7141:
! 7142: /* Add the constraints to the IdxScan object */
! 7143: for(i=0; i<pIdxInfo->nConstraint; i++){
! 7144: struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
! 7145: if( pCons->usable
! 7146: && pCons->iColumn>=0
! 7147: && p->pTab->aCol[pCons->iColumn].iPk==0
! 7148: && (pCons->op & opmask)
! 7149: ){
! 7150: IdxConstraint *pNew;
! 7151: const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
! 7152: pNew = idxNewConstraint(&rc, zColl);
! 7153: if( pNew ){
! 7154: pNew->iCol = pCons->iColumn;
! 7155: if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 7156: pNew->pNext = pScan->pEq;
! 7157: pScan->pEq = pNew;
! 7158: }else{
! 7159: pNew->bRange = 1;
! 7160: pNew->pNext = pScan->pRange;
! 7161: pScan->pRange = pNew;
! 7162: }
! 7163: }
! 7164: n++;
! 7165: pIdxInfo->aConstraintUsage[i].argvIndex = n;
! 7166: }
! 7167: }
! 7168:
! 7169: /* Add the ORDER BY to the IdxScan object */
! 7170: for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
! 7171: int iCol = pIdxInfo->aOrderBy[i].iColumn;
! 7172: if( iCol>=0 ){
! 7173: IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
! 7174: if( pNew ){
! 7175: pNew->iCol = iCol;
! 7176: pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
! 7177: pNew->pNext = pScan->pOrder;
! 7178: pNew->pLink = pScan->pOrder;
! 7179: pScan->pOrder = pNew;
! 7180: n++;
! 7181: }
! 7182: }
! 7183: }
! 7184: }
! 7185:
! 7186: pIdxInfo->estimatedCost = 1000000.0 / (n+1);
! 7187: return rc;
! 7188: }
! 7189:
! 7190: static int expertUpdate(
! 7191: sqlite3_vtab *pVtab,
! 7192: int nData,
! 7193: sqlite3_value **azData,
! 7194: sqlite_int64 *pRowid
! 7195: ){
! 7196: (void)pVtab;
! 7197: (void)nData;
! 7198: (void)azData;
! 7199: (void)pRowid;
! 7200: return SQLITE_OK;
! 7201: }
! 7202:
! 7203: /*
! 7204: ** Virtual table module xOpen method.
! 7205: */
! 7206: static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
! 7207: int rc = SQLITE_OK;
! 7208: ExpertCsr *pCsr;
! 7209: (void)pVTab;
! 7210: pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
! 7211: *ppCursor = (sqlite3_vtab_cursor*)pCsr;
! 7212: return rc;
! 7213: }
! 7214:
! 7215: /*
! 7216: ** Virtual table module xClose method.
! 7217: */
! 7218: static int expertClose(sqlite3_vtab_cursor *cur){
! 7219: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 7220: sqlite3_finalize(pCsr->pData);
! 7221: sqlite3_free(pCsr);
! 7222: return SQLITE_OK;
! 7223: }
! 7224:
! 7225: /*
! 7226: ** Virtual table module xEof method.
! 7227: **
! 7228: ** Return non-zero if the cursor does not currently point to a valid
! 7229: ** record (i.e if the scan has finished), or zero otherwise.
! 7230: */
! 7231: static int expertEof(sqlite3_vtab_cursor *cur){
! 7232: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 7233: return pCsr->pData==0;
! 7234: }
! 7235:
! 7236: /*
! 7237: ** Virtual table module xNext method.
! 7238: */
! 7239: static int expertNext(sqlite3_vtab_cursor *cur){
! 7240: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 7241: int rc = SQLITE_OK;
! 7242:
! 7243: assert( pCsr->pData );
! 7244: rc = sqlite3_step(pCsr->pData);
! 7245: if( rc!=SQLITE_ROW ){
! 7246: rc = sqlite3_finalize(pCsr->pData);
! 7247: pCsr->pData = 0;
! 7248: }else{
! 7249: rc = SQLITE_OK;
! 7250: }
! 7251:
! 7252: return rc;
! 7253: }
! 7254:
! 7255: /*
! 7256: ** Virtual table module xRowid method.
! 7257: */
! 7258: static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 7259: (void)cur;
! 7260: *pRowid = 0;
! 7261: return SQLITE_OK;
! 7262: }
! 7263:
! 7264: /*
! 7265: ** Virtual table module xColumn method.
! 7266: */
! 7267: static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
! 7268: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 7269: sqlite3_value *pVal;
! 7270: pVal = sqlite3_column_value(pCsr->pData, i);
! 7271: if( pVal ){
! 7272: sqlite3_result_value(ctx, pVal);
! 7273: }
! 7274: return SQLITE_OK;
! 7275: }
! 7276:
! 7277: /*
! 7278: ** Virtual table module xFilter method.
! 7279: */
! 7280: static int expertFilter(
! 7281: sqlite3_vtab_cursor *cur,
! 7282: int idxNum, const char *idxStr,
! 7283: int argc, sqlite3_value **argv
! 7284: ){
! 7285: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 7286: ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
! 7287: sqlite3expert *pExpert = pVtab->pExpert;
! 7288: int rc;
! 7289:
! 7290: (void)idxNum;
! 7291: (void)idxStr;
! 7292: (void)argc;
! 7293: (void)argv;
! 7294: rc = sqlite3_finalize(pCsr->pData);
! 7295: pCsr->pData = 0;
! 7296: if( rc==SQLITE_OK ){
! 7297: rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
! 7298: "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
! 7299: );
! 7300: }
! 7301:
! 7302: if( rc==SQLITE_OK ){
! 7303: rc = expertNext(cur);
! 7304: }
! 7305: return rc;
! 7306: }
! 7307:
! 7308: static int idxRegisterVtab(sqlite3expert *p){
! 7309: static sqlite3_module expertModule = {
! 7310: 2, /* iVersion */
! 7311: expertConnect, /* xCreate - create a table */
! 7312: expertConnect, /* xConnect - connect to an existing table */
! 7313: expertBestIndex, /* xBestIndex - Determine search strategy */
! 7314: expertDisconnect, /* xDisconnect - Disconnect from a table */
! 7315: expertDisconnect, /* xDestroy - Drop a table */
! 7316: expertOpen, /* xOpen - open a cursor */
! 7317: expertClose, /* xClose - close a cursor */
! 7318: expertFilter, /* xFilter - configure scan constraints */
! 7319: expertNext, /* xNext - advance a cursor */
! 7320: expertEof, /* xEof */
! 7321: expertColumn, /* xColumn - read data */
! 7322: expertRowid, /* xRowid - read data */
! 7323: expertUpdate, /* xUpdate - write data */
! 7324: 0, /* xBegin - begin transaction */
! 7325: 0, /* xSync - sync transaction */
! 7326: 0, /* xCommit - commit transaction */
! 7327: 0, /* xRollback - rollback transaction */
! 7328: 0, /* xFindFunction - function overloading */
! 7329: 0, /* xRename - rename the table */
! 7330: 0, /* xSavepoint */
! 7331: 0, /* xRelease */
! 7332: 0, /* xRollbackTo */
! 7333: 0, /* xShadowName */
! 7334: };
! 7335:
! 7336: return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
! 7337: }
! 7338: /*
! 7339: ** End of virtual table implementation.
! 7340: *************************************************************************/
! 7341: /*
! 7342: ** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
! 7343: ** is called, set it to the return value of sqlite3_finalize() before
! 7344: ** returning. Otherwise, discard the sqlite3_finalize() return value.
! 7345: */
! 7346: static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
! 7347: int rc = sqlite3_finalize(pStmt);
! 7348: if( *pRc==SQLITE_OK ) *pRc = rc;
! 7349: }
! 7350:
! 7351: /*
! 7352: ** Attempt to allocate an IdxTable structure corresponding to table zTab
! 7353: ** in the main database of connection db. If successful, set (*ppOut) to
! 7354: ** point to the new object and return SQLITE_OK. Otherwise, return an
! 7355: ** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
! 7356: ** set to point to an error string.
! 7357: **
! 7358: ** It is the responsibility of the caller to eventually free either the
! 7359: ** IdxTable object or error message using sqlite3_free().
! 7360: */
! 7361: static int idxGetTableInfo(
! 7362: sqlite3 *db, /* Database connection to read details from */
! 7363: const char *zTab, /* Table name */
! 7364: IdxTable **ppOut, /* OUT: New object (if successful) */
! 7365: char **pzErrmsg /* OUT: Error message (if not) */
! 7366: ){
! 7367: sqlite3_stmt *p1 = 0;
! 7368: int nCol = 0;
! 7369: int nTab = STRLEN(zTab);
! 7370: int nByte = sizeof(IdxTable) + nTab + 1;
! 7371: IdxTable *pNew = 0;
! 7372: int rc, rc2;
! 7373: char *pCsr = 0;
! 7374:
! 7375: rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
! 7376: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
! 7377: const char *zCol = (const char*)sqlite3_column_text(p1, 1);
! 7378: nByte += 1 + STRLEN(zCol);
! 7379: rc = sqlite3_table_column_metadata(
! 7380: db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
! 7381: );
! 7382: nByte += 1 + STRLEN(zCol);
! 7383: nCol++;
! 7384: }
! 7385: rc2 = sqlite3_reset(p1);
! 7386: if( rc==SQLITE_OK ) rc = rc2;
! 7387:
! 7388: nByte += sizeof(IdxColumn) * nCol;
! 7389: if( rc==SQLITE_OK ){
! 7390: pNew = idxMalloc(&rc, nByte);
! 7391: }
! 7392: if( rc==SQLITE_OK ){
! 7393: pNew->aCol = (IdxColumn*)&pNew[1];
! 7394: pNew->nCol = nCol;
! 7395: pCsr = (char*)&pNew->aCol[nCol];
! 7396: }
! 7397:
! 7398: nCol = 0;
! 7399: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
! 7400: const char *zCol = (const char*)sqlite3_column_text(p1, 1);
! 7401: int nCopy = STRLEN(zCol) + 1;
! 7402: pNew->aCol[nCol].zName = pCsr;
! 7403: pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
! 7404: memcpy(pCsr, zCol, nCopy);
! 7405: pCsr += nCopy;
! 7406:
! 7407: rc = sqlite3_table_column_metadata(
! 7408: db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
! 7409: );
! 7410: if( rc==SQLITE_OK ){
! 7411: nCopy = STRLEN(zCol) + 1;
! 7412: pNew->aCol[nCol].zColl = pCsr;
! 7413: memcpy(pCsr, zCol, nCopy);
! 7414: pCsr += nCopy;
! 7415: }
! 7416:
! 7417: nCol++;
! 7418: }
! 7419: idxFinalize(&rc, p1);
! 7420:
! 7421: if( rc!=SQLITE_OK ){
! 7422: sqlite3_free(pNew);
! 7423: pNew = 0;
! 7424: }else{
! 7425: pNew->zName = pCsr;
! 7426: memcpy(pNew->zName, zTab, nTab+1);
! 7427: }
! 7428:
! 7429: *ppOut = pNew;
! 7430: return rc;
! 7431: }
! 7432:
! 7433: /*
! 7434: ** This function is a no-op if *pRc is set to anything other than
! 7435: ** SQLITE_OK when it is called.
! 7436: **
! 7437: ** If *pRc is initially set to SQLITE_OK, then the text specified by
! 7438: ** the printf() style arguments is appended to zIn and the result returned
! 7439: ** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
! 7440: ** zIn before returning.
! 7441: */
! 7442: static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
! 7443: va_list ap;
! 7444: char *zAppend = 0;
! 7445: char *zRet = 0;
! 7446: int nIn = zIn ? STRLEN(zIn) : 0;
! 7447: int nAppend = 0;
! 7448: va_start(ap, zFmt);
! 7449: if( *pRc==SQLITE_OK ){
! 7450: zAppend = sqlite3_vmprintf(zFmt, ap);
! 7451: if( zAppend ){
! 7452: nAppend = STRLEN(zAppend);
! 7453: zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
! 7454: }
! 7455: if( zAppend && zRet ){
! 7456: if( nIn ) memcpy(zRet, zIn, nIn);
! 7457: memcpy(&zRet[nIn], zAppend, nAppend+1);
! 7458: }else{
! 7459: sqlite3_free(zRet);
! 7460: zRet = 0;
! 7461: *pRc = SQLITE_NOMEM;
! 7462: }
! 7463: sqlite3_free(zAppend);
! 7464: sqlite3_free(zIn);
! 7465: }
! 7466: va_end(ap);
! 7467: return zRet;
! 7468: }
! 7469:
! 7470: /*
! 7471: ** Return true if zId must be quoted in order to use it as an SQL
! 7472: ** identifier, or false otherwise.
! 7473: */
! 7474: static int idxIdentifierRequiresQuotes(const char *zId){
! 7475: int i;
! 7476: for(i=0; zId[i]; i++){
! 7477: if( !(zId[i]=='_')
! 7478: && !(zId[i]>='0' && zId[i]<='9')
! 7479: && !(zId[i]>='a' && zId[i]<='z')
! 7480: && !(zId[i]>='A' && zId[i]<='Z')
! 7481: ){
! 7482: return 1;
! 7483: }
! 7484: }
! 7485: return 0;
! 7486: }
! 7487:
! 7488: /*
! 7489: ** This function appends an index column definition suitable for constraint
! 7490: ** pCons to the string passed as zIn and returns the result.
! 7491: */
! 7492: static char *idxAppendColDefn(
! 7493: int *pRc, /* IN/OUT: Error code */
! 7494: char *zIn, /* Column defn accumulated so far */
! 7495: IdxTable *pTab, /* Table index will be created on */
! 7496: IdxConstraint *pCons
! 7497: ){
! 7498: char *zRet = zIn;
! 7499: IdxColumn *p = &pTab->aCol[pCons->iCol];
! 7500: if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
! 7501:
! 7502: if( idxIdentifierRequiresQuotes(p->zName) ){
! 7503: zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
! 7504: }else{
! 7505: zRet = idxAppendText(pRc, zRet, "%s", p->zName);
! 7506: }
! 7507:
! 7508: if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
! 7509: if( idxIdentifierRequiresQuotes(pCons->zColl) ){
! 7510: zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
! 7511: }else{
! 7512: zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
! 7513: }
! 7514: }
! 7515:
! 7516: if( pCons->bDesc ){
! 7517: zRet = idxAppendText(pRc, zRet, " DESC");
! 7518: }
! 7519: return zRet;
! 7520: }
! 7521:
! 7522: /*
! 7523: ** Search database dbm for an index compatible with the one idxCreateFromCons()
! 7524: ** would create from arguments pScan, pEq and pTail. If no error occurs and
! 7525: ** such an index is found, return non-zero. Or, if no such index is found,
! 7526: ** return zero.
! 7527: **
! 7528: ** If an error occurs, set *pRc to an SQLite error code and return zero.
! 7529: */
! 7530: static int idxFindCompatible(
! 7531: int *pRc, /* OUT: Error code */
! 7532: sqlite3* dbm, /* Database to search */
! 7533: IdxScan *pScan, /* Scan for table to search for index on */
! 7534: IdxConstraint *pEq, /* List of == constraints */
! 7535: IdxConstraint *pTail /* List of range constraints */
! 7536: ){
! 7537: const char *zTbl = pScan->pTab->zName;
! 7538: sqlite3_stmt *pIdxList = 0;
! 7539: IdxConstraint *pIter;
! 7540: int nEq = 0; /* Number of elements in pEq */
! 7541: int rc;
! 7542:
! 7543: /* Count the elements in list pEq */
! 7544: for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
! 7545:
! 7546: rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
! 7547: while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
! 7548: int bMatch = 1;
! 7549: IdxConstraint *pT = pTail;
! 7550: sqlite3_stmt *pInfo = 0;
! 7551: const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
! 7552:
! 7553: /* Zero the IdxConstraint.bFlag values in the pEq list */
! 7554: for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
! 7555:
! 7556: rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
! 7557: while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
! 7558: int iIdx = sqlite3_column_int(pInfo, 0);
! 7559: int iCol = sqlite3_column_int(pInfo, 1);
! 7560: const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
! 7561:
! 7562: if( iIdx<nEq ){
! 7563: for(pIter=pEq; pIter; pIter=pIter->pLink){
! 7564: if( pIter->bFlag ) continue;
! 7565: if( pIter->iCol!=iCol ) continue;
! 7566: if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
! 7567: pIter->bFlag = 1;
! 7568: break;
! 7569: }
! 7570: if( pIter==0 ){
! 7571: bMatch = 0;
! 7572: break;
! 7573: }
! 7574: }else{
! 7575: if( pT ){
! 7576: if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
! 7577: bMatch = 0;
! 7578: break;
! 7579: }
! 7580: pT = pT->pLink;
! 7581: }
! 7582: }
! 7583: }
! 7584: idxFinalize(&rc, pInfo);
! 7585:
! 7586: if( rc==SQLITE_OK && bMatch ){
! 7587: sqlite3_finalize(pIdxList);
! 7588: return 1;
! 7589: }
! 7590: }
! 7591: idxFinalize(&rc, pIdxList);
! 7592:
! 7593: *pRc = rc;
! 7594: return 0;
! 7595: }
! 7596:
! 7597: static int idxCreateFromCons(
! 7598: sqlite3expert *p,
! 7599: IdxScan *pScan,
! 7600: IdxConstraint *pEq,
! 7601: IdxConstraint *pTail
! 7602: ){
! 7603: sqlite3 *dbm = p->dbm;
! 7604: int rc = SQLITE_OK;
! 7605: if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
! 7606: IdxTable *pTab = pScan->pTab;
! 7607: char *zCols = 0;
! 7608: char *zIdx = 0;
! 7609: IdxConstraint *pCons;
! 7610: unsigned int h = 0;
! 7611: const char *zFmt;
! 7612:
! 7613: for(pCons=pEq; pCons; pCons=pCons->pLink){
! 7614: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
! 7615: }
! 7616: for(pCons=pTail; pCons; pCons=pCons->pLink){
! 7617: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
! 7618: }
! 7619:
! 7620: if( rc==SQLITE_OK ){
! 7621: /* Hash the list of columns to come up with a name for the index */
! 7622: const char *zTable = pScan->pTab->zName;
! 7623: char *zName; /* Index name */
! 7624: int i;
! 7625: for(i=0; zCols[i]; i++){
! 7626: h += ((h<<3) + zCols[i]);
! 7627: }
! 7628: zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
! 7629: if( zName==0 ){
! 7630: rc = SQLITE_NOMEM;
! 7631: }else{
! 7632: if( idxIdentifierRequiresQuotes(zTable) ){
! 7633: zFmt = "CREATE INDEX '%q' ON %Q(%s)";
! 7634: }else{
! 7635: zFmt = "CREATE INDEX %s ON %s(%s)";
! 7636: }
! 7637: zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
! 7638: if( !zIdx ){
! 7639: rc = SQLITE_NOMEM;
! 7640: }else{
! 7641: rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
! 7642: idxHashAdd(&rc, &p->hIdx, zName, zIdx);
! 7643: }
! 7644: sqlite3_free(zName);
! 7645: sqlite3_free(zIdx);
! 7646: }
! 7647: }
! 7648:
! 7649: sqlite3_free(zCols);
! 7650: }
! 7651: return rc;
! 7652: }
! 7653:
! 7654: /*
! 7655: ** Return true if list pList (linked by IdxConstraint.pLink) contains
! 7656: ** a constraint compatible with *p. Otherwise return false.
! 7657: */
! 7658: static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
! 7659: IdxConstraint *pCmp;
! 7660: for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
! 7661: if( p->iCol==pCmp->iCol ) return 1;
! 7662: }
! 7663: return 0;
! 7664: }
! 7665:
! 7666: static int idxCreateFromWhere(
! 7667: sqlite3expert *p,
! 7668: IdxScan *pScan, /* Create indexes for this scan */
! 7669: IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */
! 7670: ){
! 7671: IdxConstraint *p1 = 0;
! 7672: IdxConstraint *pCon;
! 7673: int rc;
! 7674:
! 7675: /* Gather up all the == constraints. */
! 7676: for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
! 7677: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
! 7678: pCon->pLink = p1;
! 7679: p1 = pCon;
! 7680: }
! 7681: }
! 7682:
! 7683: /* Create an index using the == constraints collected above. And the
! 7684: ** range constraint/ORDER BY terms passed in by the caller, if any. */
! 7685: rc = idxCreateFromCons(p, pScan, p1, pTail);
! 7686:
! 7687: /* If no range/ORDER BY passed by the caller, create a version of the
! 7688: ** index for each range constraint. */
! 7689: if( pTail==0 ){
! 7690: for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
! 7691: assert( pCon->pLink==0 );
! 7692: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
! 7693: rc = idxCreateFromCons(p, pScan, p1, pCon);
! 7694: }
! 7695: }
! 7696: }
! 7697:
! 7698: return rc;
! 7699: }
! 7700:
! 7701: /*
! 7702: ** Create candidate indexes in database [dbm] based on the data in
! 7703: ** linked-list pScan.
! 7704: */
! 7705: static int idxCreateCandidates(sqlite3expert *p){
! 7706: int rc = SQLITE_OK;
! 7707: IdxScan *pIter;
! 7708:
! 7709: for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
! 7710: rc = idxCreateFromWhere(p, pIter, 0);
! 7711: if( rc==SQLITE_OK && pIter->pOrder ){
! 7712: rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
! 7713: }
! 7714: }
! 7715:
! 7716: return rc;
! 7717: }
! 7718:
! 7719: /*
! 7720: ** Free all elements of the linked list starting at pConstraint.
! 7721: */
! 7722: static void idxConstraintFree(IdxConstraint *pConstraint){
! 7723: IdxConstraint *pNext;
! 7724: IdxConstraint *p;
! 7725:
! 7726: for(p=pConstraint; p; p=pNext){
! 7727: pNext = p->pNext;
! 7728: sqlite3_free(p);
! 7729: }
! 7730: }
! 7731:
! 7732: /*
! 7733: ** Free all elements of the linked list starting from pScan up until pLast
! 7734: ** (pLast is not freed).
! 7735: */
! 7736: static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
! 7737: IdxScan *p;
! 7738: IdxScan *pNext;
! 7739: for(p=pScan; p!=pLast; p=pNext){
! 7740: pNext = p->pNextScan;
! 7741: idxConstraintFree(p->pOrder);
! 7742: idxConstraintFree(p->pEq);
! 7743: idxConstraintFree(p->pRange);
! 7744: sqlite3_free(p);
! 7745: }
! 7746: }
! 7747:
! 7748: /*
! 7749: ** Free all elements of the linked list starting from pStatement up
! 7750: ** until pLast (pLast is not freed).
! 7751: */
! 7752: static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
! 7753: IdxStatement *p;
! 7754: IdxStatement *pNext;
! 7755: for(p=pStatement; p!=pLast; p=pNext){
! 7756: pNext = p->pNext;
! 7757: sqlite3_free(p->zEQP);
! 7758: sqlite3_free(p->zIdx);
! 7759: sqlite3_free(p);
! 7760: }
! 7761: }
! 7762:
! 7763: /*
! 7764: ** Free the linked list of IdxTable objects starting at pTab.
! 7765: */
! 7766: static void idxTableFree(IdxTable *pTab){
! 7767: IdxTable *pIter;
! 7768: IdxTable *pNext;
! 7769: for(pIter=pTab; pIter; pIter=pNext){
! 7770: pNext = pIter->pNext;
! 7771: sqlite3_free(pIter);
! 7772: }
! 7773: }
! 7774:
! 7775: /*
! 7776: ** Free the linked list of IdxWrite objects starting at pTab.
! 7777: */
! 7778: static void idxWriteFree(IdxWrite *pTab){
! 7779: IdxWrite *pIter;
! 7780: IdxWrite *pNext;
! 7781: for(pIter=pTab; pIter; pIter=pNext){
! 7782: pNext = pIter->pNext;
! 7783: sqlite3_free(pIter);
! 7784: }
! 7785: }
! 7786:
! 7787:
! 7788:
! 7789: /*
! 7790: ** This function is called after candidate indexes have been created. It
! 7791: ** runs all the queries to see which indexes they prefer, and populates
! 7792: ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
! 7793: */
! 7794: int idxFindIndexes(
! 7795: sqlite3expert *p,
! 7796: char **pzErr /* OUT: Error message (sqlite3_malloc) */
! 7797: ){
! 7798: IdxStatement *pStmt;
! 7799: sqlite3 *dbm = p->dbm;
! 7800: int rc = SQLITE_OK;
! 7801:
! 7802: IdxHash hIdx;
! 7803: idxHashInit(&hIdx);
! 7804:
! 7805: for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
! 7806: IdxHashEntry *pEntry;
! 7807: sqlite3_stmt *pExplain = 0;
! 7808: idxHashClear(&hIdx);
! 7809: rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
! 7810: "EXPLAIN QUERY PLAN %s", pStmt->zSql
! 7811: );
! 7812: while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
! 7813: /* int iId = sqlite3_column_int(pExplain, 0); */
! 7814: /* int iParent = sqlite3_column_int(pExplain, 1); */
! 7815: /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
! 7816: const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
! 7817: int nDetail = STRLEN(zDetail);
! 7818: int i;
! 7819:
! 7820: for(i=0; i<nDetail; i++){
! 7821: const char *zIdx = 0;
! 7822: if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
! 7823: zIdx = &zDetail[i+13];
! 7824: }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
! 7825: zIdx = &zDetail[i+22];
! 7826: }
! 7827: if( zIdx ){
! 7828: const char *zSql;
! 7829: int nIdx = 0;
! 7830: while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
! 7831: nIdx++;
! 7832: }
! 7833: zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
! 7834: if( zSql ){
! 7835: idxHashAdd(&rc, &hIdx, zSql, 0);
! 7836: if( rc ) goto find_indexes_out;
! 7837: }
! 7838: break;
! 7839: }
! 7840: }
! 7841:
! 7842: if( zDetail[0]!='-' ){
! 7843: pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
! 7844: }
! 7845: }
! 7846:
! 7847: for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
! 7848: pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
! 7849: }
! 7850:
! 7851: idxFinalize(&rc, pExplain);
! 7852: }
! 7853:
! 7854: find_indexes_out:
! 7855: idxHashClear(&hIdx);
! 7856: return rc;
! 7857: }
! 7858:
! 7859: static int idxAuthCallback(
! 7860: void *pCtx,
! 7861: int eOp,
! 7862: const char *z3,
! 7863: const char *z4,
! 7864: const char *zDb,
! 7865: const char *zTrigger
! 7866: ){
! 7867: int rc = SQLITE_OK;
! 7868: (void)z4;
! 7869: (void)zTrigger;
! 7870: if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
! 7871: if( sqlite3_stricmp(zDb, "main")==0 ){
! 7872: sqlite3expert *p = (sqlite3expert*)pCtx;
! 7873: IdxTable *pTab;
! 7874: for(pTab=p->pTable; pTab; pTab=pTab->pNext){
! 7875: if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
! 7876: }
! 7877: if( pTab ){
! 7878: IdxWrite *pWrite;
! 7879: for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
! 7880: if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
! 7881: }
! 7882: if( pWrite==0 ){
! 7883: pWrite = idxMalloc(&rc, sizeof(IdxWrite));
! 7884: if( rc==SQLITE_OK ){
! 7885: pWrite->pTab = pTab;
! 7886: pWrite->eOp = eOp;
! 7887: pWrite->pNext = p->pWrite;
! 7888: p->pWrite = pWrite;
! 7889: }
! 7890: }
! 7891: }
! 7892: }
! 7893: }
! 7894: return rc;
! 7895: }
! 7896:
! 7897: static int idxProcessOneTrigger(
! 7898: sqlite3expert *p,
! 7899: IdxWrite *pWrite,
! 7900: char **pzErr
! 7901: ){
! 7902: static const char *zInt = UNIQUE_TABLE_NAME;
! 7903: static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
! 7904: IdxTable *pTab = pWrite->pTab;
! 7905: const char *zTab = pTab->zName;
! 7906: const char *zSql =
! 7907: "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
! 7908: "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
! 7909: "ORDER BY type;";
! 7910: sqlite3_stmt *pSelect = 0;
! 7911: int rc = SQLITE_OK;
! 7912: char *zWrite = 0;
! 7913:
! 7914: /* Create the table and its triggers in the temp schema */
! 7915: rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
! 7916: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
! 7917: const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
! 7918: rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
! 7919: }
! 7920: idxFinalize(&rc, pSelect);
! 7921:
! 7922: /* Rename the table in the temp schema to zInt */
! 7923: if( rc==SQLITE_OK ){
! 7924: char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
! 7925: if( z==0 ){
! 7926: rc = SQLITE_NOMEM;
! 7927: }else{
! 7928: rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
! 7929: sqlite3_free(z);
! 7930: }
! 7931: }
! 7932:
! 7933: switch( pWrite->eOp ){
! 7934: case SQLITE_INSERT: {
! 7935: int i;
! 7936: zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
! 7937: for(i=0; i<pTab->nCol; i++){
! 7938: zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
! 7939: }
! 7940: zWrite = idxAppendText(&rc, zWrite, ")");
! 7941: break;
! 7942: }
! 7943: case SQLITE_UPDATE: {
! 7944: int i;
! 7945: zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
! 7946: for(i=0; i<pTab->nCol; i++){
! 7947: zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
! 7948: pTab->aCol[i].zName
! 7949: );
! 7950: }
! 7951: break;
! 7952: }
! 7953: default: {
! 7954: assert( pWrite->eOp==SQLITE_DELETE );
! 7955: if( rc==SQLITE_OK ){
! 7956: zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
! 7957: if( zWrite==0 ) rc = SQLITE_NOMEM;
! 7958: }
! 7959: }
! 7960: }
! 7961:
! 7962: if( rc==SQLITE_OK ){
! 7963: sqlite3_stmt *pX = 0;
! 7964: rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
! 7965: idxFinalize(&rc, pX);
! 7966: if( rc!=SQLITE_OK ){
! 7967: idxDatabaseError(p->dbv, pzErr);
! 7968: }
! 7969: }
! 7970: sqlite3_free(zWrite);
! 7971:
! 7972: if( rc==SQLITE_OK ){
! 7973: rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
! 7974: }
! 7975:
! 7976: return rc;
! 7977: }
! 7978:
! 7979: static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
! 7980: int rc = SQLITE_OK;
! 7981: IdxWrite *pEnd = 0;
! 7982: IdxWrite *pFirst = p->pWrite;
! 7983:
! 7984: while( rc==SQLITE_OK && pFirst!=pEnd ){
! 7985: IdxWrite *pIter;
! 7986: for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
! 7987: rc = idxProcessOneTrigger(p, pIter, pzErr);
! 7988: }
! 7989: pEnd = pFirst;
! 7990: pFirst = p->pWrite;
! 7991: }
! 7992:
! 7993: return rc;
! 7994: }
! 7995:
! 7996:
! 7997: static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
! 7998: int rc = idxRegisterVtab(p);
! 7999: sqlite3_stmt *pSchema = 0;
! 8000:
! 8001: /* For each table in the main db schema:
! 8002: **
! 8003: ** 1) Add an entry to the p->pTable list, and
! 8004: ** 2) Create the equivalent virtual table in dbv.
! 8005: */
! 8006: rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
! 8007: "SELECT type, name, sql, 1 FROM sqlite_master "
! 8008: "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
! 8009: " UNION ALL "
! 8010: "SELECT type, name, sql, 2 FROM sqlite_master "
! 8011: "WHERE type = 'trigger'"
! 8012: " AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
! 8013: "ORDER BY 4, 1"
! 8014: );
! 8015: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
! 8016: const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
! 8017: const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
! 8018: const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
! 8019:
! 8020: if( zType[0]=='v' || zType[1]=='r' ){
! 8021: rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
! 8022: }else{
! 8023: IdxTable *pTab;
! 8024: rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
! 8025: if( rc==SQLITE_OK ){
! 8026: int i;
! 8027: char *zInner = 0;
! 8028: char *zOuter = 0;
! 8029: pTab->pNext = p->pTable;
! 8030: p->pTable = pTab;
! 8031:
! 8032: /* The statement the vtab will pass to sqlite3_declare_vtab() */
! 8033: zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
! 8034: for(i=0; i<pTab->nCol; i++){
! 8035: zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
! 8036: (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
! 8037: );
! 8038: }
! 8039: zInner = idxAppendText(&rc, zInner, ")");
! 8040:
! 8041: /* The CVT statement to create the vtab */
! 8042: zOuter = idxAppendText(&rc, 0,
! 8043: "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
! 8044: );
! 8045: if( rc==SQLITE_OK ){
! 8046: rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
! 8047: }
! 8048: sqlite3_free(zInner);
! 8049: sqlite3_free(zOuter);
! 8050: }
! 8051: }
! 8052: }
! 8053: idxFinalize(&rc, pSchema);
! 8054: return rc;
! 8055: }
! 8056:
! 8057: struct IdxSampleCtx {
! 8058: int iTarget;
! 8059: double target; /* Target nRet/nRow value */
! 8060: double nRow; /* Number of rows seen */
! 8061: double nRet; /* Number of rows returned */
! 8062: };
! 8063:
! 8064: static void idxSampleFunc(
! 8065: sqlite3_context *pCtx,
! 8066: int argc,
! 8067: sqlite3_value **argv
! 8068: ){
! 8069: struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
! 8070: int bRet;
! 8071:
! 8072: (void)argv;
! 8073: assert( argc==0 );
! 8074: if( p->nRow==0.0 ){
! 8075: bRet = 1;
! 8076: }else{
! 8077: bRet = (p->nRet / p->nRow) <= p->target;
! 8078: if( bRet==0 ){
! 8079: unsigned short rnd;
! 8080: sqlite3_randomness(2, (void*)&rnd);
! 8081: bRet = ((int)rnd % 100) <= p->iTarget;
! 8082: }
! 8083: }
! 8084:
! 8085: sqlite3_result_int(pCtx, bRet);
! 8086: p->nRow += 1.0;
! 8087: p->nRet += (double)bRet;
! 8088: }
! 8089:
! 8090: struct IdxRemCtx {
! 8091: int nSlot;
! 8092: struct IdxRemSlot {
! 8093: int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
! 8094: i64 iVal; /* SQLITE_INTEGER value */
! 8095: double rVal; /* SQLITE_FLOAT value */
! 8096: int nByte; /* Bytes of space allocated at z */
! 8097: int n; /* Size of buffer z */
! 8098: char *z; /* SQLITE_TEXT/BLOB value */
! 8099: } aSlot[1];
! 8100: };
! 8101:
! 8102: /*
! 8103: ** Implementation of scalar function rem().
! 8104: */
! 8105: static void idxRemFunc(
! 8106: sqlite3_context *pCtx,
! 8107: int argc,
! 8108: sqlite3_value **argv
! 8109: ){
! 8110: struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
! 8111: struct IdxRemSlot *pSlot;
! 8112: int iSlot;
! 8113: assert( argc==2 );
! 8114:
! 8115: iSlot = sqlite3_value_int(argv[0]);
! 8116: assert( iSlot<=p->nSlot );
! 8117: pSlot = &p->aSlot[iSlot];
! 8118:
! 8119: switch( pSlot->eType ){
! 8120: case SQLITE_NULL:
! 8121: /* no-op */
! 8122: break;
! 8123:
! 8124: case SQLITE_INTEGER:
! 8125: sqlite3_result_int64(pCtx, pSlot->iVal);
! 8126: break;
! 8127:
! 8128: case SQLITE_FLOAT:
! 8129: sqlite3_result_double(pCtx, pSlot->rVal);
! 8130: break;
! 8131:
! 8132: case SQLITE_BLOB:
! 8133: sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
! 8134: break;
! 8135:
! 8136: case SQLITE_TEXT:
! 8137: sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
! 8138: break;
! 8139: }
! 8140:
! 8141: pSlot->eType = sqlite3_value_type(argv[1]);
! 8142: switch( pSlot->eType ){
! 8143: case SQLITE_NULL:
! 8144: /* no-op */
! 8145: break;
! 8146:
! 8147: case SQLITE_INTEGER:
! 8148: pSlot->iVal = sqlite3_value_int64(argv[1]);
! 8149: break;
! 8150:
! 8151: case SQLITE_FLOAT:
! 8152: pSlot->rVal = sqlite3_value_double(argv[1]);
! 8153: break;
! 8154:
! 8155: case SQLITE_BLOB:
! 8156: case SQLITE_TEXT: {
! 8157: int nByte = sqlite3_value_bytes(argv[1]);
! 8158: if( nByte>pSlot->nByte ){
! 8159: char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
! 8160: if( zNew==0 ){
! 8161: sqlite3_result_error_nomem(pCtx);
! 8162: return;
! 8163: }
! 8164: pSlot->nByte = nByte*2;
! 8165: pSlot->z = zNew;
! 8166: }
! 8167: pSlot->n = nByte;
! 8168: if( pSlot->eType==SQLITE_BLOB ){
! 8169: memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
! 8170: }else{
! 8171: memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
! 8172: }
! 8173: break;
! 8174: }
! 8175: }
! 8176: }
! 8177:
! 8178: static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
! 8179: int rc = SQLITE_OK;
! 8180: const char *zMax =
! 8181: "SELECT max(i.seqno) FROM "
! 8182: " sqlite_master AS s, "
! 8183: " pragma_index_list(s.name) AS l, "
! 8184: " pragma_index_info(l.name) AS i "
! 8185: "WHERE s.type = 'table'";
! 8186: sqlite3_stmt *pMax = 0;
! 8187:
! 8188: *pnMax = 0;
! 8189: rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
! 8190: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
! 8191: *pnMax = sqlite3_column_int(pMax, 0) + 1;
! 8192: }
! 8193: idxFinalize(&rc, pMax);
! 8194:
! 8195: return rc;
! 8196: }
! 8197:
! 8198: static int idxPopulateOneStat1(
! 8199: sqlite3expert *p,
! 8200: sqlite3_stmt *pIndexXInfo,
! 8201: sqlite3_stmt *pWriteStat,
! 8202: const char *zTab,
! 8203: const char *zIdx,
! 8204: char **pzErr
! 8205: ){
! 8206: char *zCols = 0;
! 8207: char *zOrder = 0;
! 8208: char *zQuery = 0;
! 8209: int nCol = 0;
! 8210: int i;
! 8211: sqlite3_stmt *pQuery = 0;
! 8212: int *aStat = 0;
! 8213: int rc = SQLITE_OK;
! 8214:
! 8215: assert( p->iSample>0 );
! 8216:
! 8217: /* Formulate the query text */
! 8218: sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
! 8219: while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
! 8220: const char *zComma = zCols==0 ? "" : ", ";
! 8221: const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
! 8222: const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
! 8223: zCols = idxAppendText(&rc, zCols,
! 8224: "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
! 8225: );
! 8226: zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
! 8227: }
! 8228: sqlite3_reset(pIndexXInfo);
! 8229: if( rc==SQLITE_OK ){
! 8230: if( p->iSample==100 ){
! 8231: zQuery = sqlite3_mprintf(
! 8232: "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
! 8233: );
! 8234: }else{
! 8235: zQuery = sqlite3_mprintf(
! 8236: "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
! 8237: );
! 8238: }
! 8239: }
! 8240: sqlite3_free(zCols);
! 8241: sqlite3_free(zOrder);
! 8242:
! 8243: /* Formulate the query text */
! 8244: if( rc==SQLITE_OK ){
! 8245: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
! 8246: rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
! 8247: }
! 8248: sqlite3_free(zQuery);
! 8249:
! 8250: if( rc==SQLITE_OK ){
! 8251: aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
! 8252: }
! 8253: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
! 8254: IdxHashEntry *pEntry;
! 8255: char *zStat = 0;
! 8256: for(i=0; i<=nCol; i++) aStat[i] = 1;
! 8257: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
! 8258: aStat[0]++;
! 8259: for(i=0; i<nCol; i++){
! 8260: if( sqlite3_column_int(pQuery, i)==0 ) break;
! 8261: }
! 8262: for(/*no-op*/; i<nCol; i++){
! 8263: aStat[i+1]++;
! 8264: }
! 8265: }
! 8266:
! 8267: if( rc==SQLITE_OK ){
! 8268: int s0 = aStat[0];
! 8269: zStat = sqlite3_mprintf("%d", s0);
! 8270: if( zStat==0 ) rc = SQLITE_NOMEM;
! 8271: for(i=1; rc==SQLITE_OK && i<=nCol; i++){
! 8272: zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
! 8273: }
! 8274: }
! 8275:
! 8276: if( rc==SQLITE_OK ){
! 8277: sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
! 8278: sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
! 8279: sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
! 8280: sqlite3_step(pWriteStat);
! 8281: rc = sqlite3_reset(pWriteStat);
! 8282: }
! 8283:
! 8284: pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
! 8285: if( pEntry ){
! 8286: assert( pEntry->zVal2==0 );
! 8287: pEntry->zVal2 = zStat;
! 8288: }else{
! 8289: sqlite3_free(zStat);
! 8290: }
! 8291: }
! 8292: sqlite3_free(aStat);
! 8293: idxFinalize(&rc, pQuery);
! 8294:
! 8295: return rc;
! 8296: }
! 8297:
! 8298: static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
! 8299: int rc;
! 8300: char *zSql;
! 8301:
! 8302: rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
! 8303: if( rc!=SQLITE_OK ) return rc;
! 8304:
! 8305: zSql = sqlite3_mprintf(
! 8306: "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
! 8307: );
! 8308: if( zSql==0 ) return SQLITE_NOMEM;
! 8309: rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
! 8310: sqlite3_free(zSql);
! 8311:
! 8312: return rc;
! 8313: }
! 8314:
! 8315: /*
! 8316: ** This function is called as part of sqlite3_expert_analyze(). Candidate
! 8317: ** indexes have already been created in database sqlite3expert.dbm, this
! 8318: ** function populates sqlite_stat1 table in the same database.
! 8319: **
! 8320: ** The stat1 data is generated by querying the
! 8321: */
! 8322: static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
! 8323: int rc = SQLITE_OK;
! 8324: int nMax =0;
! 8325: struct IdxRemCtx *pCtx = 0;
! 8326: struct IdxSampleCtx samplectx;
! 8327: int i;
! 8328: i64 iPrev = -100000;
! 8329: sqlite3_stmt *pAllIndex = 0;
! 8330: sqlite3_stmt *pIndexXInfo = 0;
! 8331: sqlite3_stmt *pWrite = 0;
! 8332:
! 8333: const char *zAllIndex =
! 8334: "SELECT s.rowid, s.name, l.name FROM "
! 8335: " sqlite_master AS s, "
! 8336: " pragma_index_list(s.name) AS l "
! 8337: "WHERE s.type = 'table'";
! 8338: const char *zIndexXInfo =
! 8339: "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
! 8340: const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
! 8341:
! 8342: /* If iSample==0, no sqlite_stat1 data is required. */
! 8343: if( p->iSample==0 ) return SQLITE_OK;
! 8344:
! 8345: rc = idxLargestIndex(p->dbm, &nMax, pzErr);
! 8346: if( nMax<=0 || rc!=SQLITE_OK ) return rc;
! 8347:
! 8348: rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
! 8349:
! 8350: if( rc==SQLITE_OK ){
! 8351: int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
! 8352: pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
! 8353: }
! 8354:
! 8355: if( rc==SQLITE_OK ){
! 8356: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
! 8357: rc = sqlite3_create_function(
! 8358: dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
! 8359: );
! 8360: }
! 8361: if( rc==SQLITE_OK ){
! 8362: rc = sqlite3_create_function(
! 8363: p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
! 8364: );
! 8365: }
! 8366:
! 8367: if( rc==SQLITE_OK ){
! 8368: pCtx->nSlot = nMax+1;
! 8369: rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
! 8370: }
! 8371: if( rc==SQLITE_OK ){
! 8372: rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
! 8373: }
! 8374: if( rc==SQLITE_OK ){
! 8375: rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
! 8376: }
! 8377:
! 8378: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
! 8379: i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
! 8380: const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
! 8381: const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
! 8382: if( p->iSample<100 && iPrev!=iRowid ){
! 8383: samplectx.target = (double)p->iSample / 100.0;
! 8384: samplectx.iTarget = p->iSample;
! 8385: samplectx.nRow = 0.0;
! 8386: samplectx.nRet = 0.0;
! 8387: rc = idxBuildSampleTable(p, zTab);
! 8388: if( rc!=SQLITE_OK ) break;
! 8389: }
! 8390: rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
! 8391: iPrev = iRowid;
! 8392: }
! 8393: if( rc==SQLITE_OK && p->iSample<100 ){
! 8394: rc = sqlite3_exec(p->dbv,
! 8395: "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
! 8396: );
! 8397: }
! 8398:
! 8399: idxFinalize(&rc, pAllIndex);
! 8400: idxFinalize(&rc, pIndexXInfo);
! 8401: idxFinalize(&rc, pWrite);
! 8402:
! 8403: for(i=0; i<pCtx->nSlot; i++){
! 8404: sqlite3_free(pCtx->aSlot[i].z);
! 8405: }
! 8406: sqlite3_free(pCtx);
! 8407:
! 8408: if( rc==SQLITE_OK ){
! 8409: rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
! 8410: }
! 8411:
! 8412: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
! 8413: return rc;
! 8414: }
! 8415:
! 8416: /*
! 8417: ** Allocate a new sqlite3expert object.
! 8418: */
! 8419: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
! 8420: int rc = SQLITE_OK;
! 8421: sqlite3expert *pNew;
! 8422:
! 8423: pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
! 8424:
! 8425: /* Open two in-memory databases to work with. The "vtab database" (dbv)
! 8426: ** will contain a virtual table corresponding to each real table in
! 8427: ** the user database schema, and a copy of each view. It is used to
! 8428: ** collect information regarding the WHERE, ORDER BY and other clauses
! 8429: ** of the user's query.
! 8430: */
! 8431: if( rc==SQLITE_OK ){
! 8432: pNew->db = db;
! 8433: pNew->iSample = 100;
! 8434: rc = sqlite3_open(":memory:", &pNew->dbv);
! 8435: }
! 8436: if( rc==SQLITE_OK ){
! 8437: rc = sqlite3_open(":memory:", &pNew->dbm);
! 8438: if( rc==SQLITE_OK ){
! 8439: sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
! 8440: }
! 8441: }
! 8442:
! 8443:
! 8444: /* Copy the entire schema of database [db] into [dbm]. */
! 8445: if( rc==SQLITE_OK ){
! 8446: sqlite3_stmt *pSql;
! 8447: rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
! 8448: "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
! 8449: " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
! 8450: );
! 8451: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
! 8452: const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
! 8453: rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
! 8454: }
! 8455: idxFinalize(&rc, pSql);
! 8456: }
! 8457:
! 8458: /* Create the vtab schema */
! 8459: if( rc==SQLITE_OK ){
! 8460: rc = idxCreateVtabSchema(pNew, pzErrmsg);
! 8461: }
! 8462:
! 8463: /* Register the auth callback with dbv */
! 8464: if( rc==SQLITE_OK ){
! 8465: sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
! 8466: }
! 8467:
! 8468: /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
! 8469: ** return the new sqlite3expert handle. */
! 8470: if( rc!=SQLITE_OK ){
! 8471: sqlite3_expert_destroy(pNew);
! 8472: pNew = 0;
! 8473: }
! 8474: return pNew;
! 8475: }
! 8476:
! 8477: /*
! 8478: ** Configure an sqlite3expert object.
! 8479: */
! 8480: int sqlite3_expert_config(sqlite3expert *p, int op, ...){
! 8481: int rc = SQLITE_OK;
! 8482: va_list ap;
! 8483: va_start(ap, op);
! 8484: switch( op ){
! 8485: case EXPERT_CONFIG_SAMPLE: {
! 8486: int iVal = va_arg(ap, int);
! 8487: if( iVal<0 ) iVal = 0;
! 8488: if( iVal>100 ) iVal = 100;
! 8489: p->iSample = iVal;
! 8490: break;
! 8491: }
! 8492: default:
! 8493: rc = SQLITE_NOTFOUND;
! 8494: break;
! 8495: }
! 8496:
! 8497: va_end(ap);
! 8498: return rc;
! 8499: }
! 8500:
! 8501: /*
! 8502: ** Add an SQL statement to the analysis.
! 8503: */
! 8504: int sqlite3_expert_sql(
! 8505: sqlite3expert *p, /* From sqlite3_expert_new() */
! 8506: const char *zSql, /* SQL statement to add */
! 8507: char **pzErr /* OUT: Error message (if any) */
! 8508: ){
! 8509: IdxScan *pScanOrig = p->pScan;
! 8510: IdxStatement *pStmtOrig = p->pStatement;
! 8511: int rc = SQLITE_OK;
! 8512: const char *zStmt = zSql;
! 8513:
! 8514: if( p->bRun ) return SQLITE_MISUSE;
! 8515:
! 8516: while( rc==SQLITE_OK && zStmt && zStmt[0] ){
! 8517: sqlite3_stmt *pStmt = 0;
! 8518: rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
! 8519: if( rc==SQLITE_OK ){
! 8520: if( pStmt ){
! 8521: IdxStatement *pNew;
! 8522: const char *z = sqlite3_sql(pStmt);
! 8523: int n = STRLEN(z);
! 8524: pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
! 8525: if( rc==SQLITE_OK ){
! 8526: pNew->zSql = (char*)&pNew[1];
! 8527: memcpy(pNew->zSql, z, n+1);
! 8528: pNew->pNext = p->pStatement;
! 8529: if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
! 8530: p->pStatement = pNew;
! 8531: }
! 8532: sqlite3_finalize(pStmt);
! 8533: }
! 8534: }else{
! 8535: idxDatabaseError(p->dbv, pzErr);
! 8536: }
! 8537: }
! 8538:
! 8539: if( rc!=SQLITE_OK ){
! 8540: idxScanFree(p->pScan, pScanOrig);
! 8541: idxStatementFree(p->pStatement, pStmtOrig);
! 8542: p->pScan = pScanOrig;
! 8543: p->pStatement = pStmtOrig;
! 8544: }
! 8545:
! 8546: return rc;
! 8547: }
! 8548:
! 8549: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
! 8550: int rc;
! 8551: IdxHashEntry *pEntry;
! 8552:
! 8553: /* Do trigger processing to collect any extra IdxScan structures */
! 8554: rc = idxProcessTriggers(p, pzErr);
! 8555:
! 8556: /* Create candidate indexes within the in-memory database file */
! 8557: if( rc==SQLITE_OK ){
! 8558: rc = idxCreateCandidates(p);
! 8559: }
! 8560:
! 8561: /* Generate the stat1 data */
! 8562: if( rc==SQLITE_OK ){
! 8563: rc = idxPopulateStat1(p, pzErr);
! 8564: }
! 8565:
! 8566: /* Formulate the EXPERT_REPORT_CANDIDATES text */
! 8567: for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
! 8568: p->zCandidates = idxAppendText(&rc, p->zCandidates,
! 8569: "%s;%s%s\n", pEntry->zVal,
! 8570: pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
! 8571: );
! 8572: }
! 8573:
! 8574: /* Figure out which of the candidate indexes are preferred by the query
! 8575: ** planner and report the results to the user. */
! 8576: if( rc==SQLITE_OK ){
! 8577: rc = idxFindIndexes(p, pzErr);
! 8578: }
! 8579:
! 8580: if( rc==SQLITE_OK ){
! 8581: p->bRun = 1;
! 8582: }
! 8583: return rc;
! 8584: }
! 8585:
! 8586: /*
! 8587: ** Return the total number of statements that have been added to this
! 8588: ** sqlite3expert using sqlite3_expert_sql().
! 8589: */
! 8590: int sqlite3_expert_count(sqlite3expert *p){
! 8591: int nRet = 0;
! 8592: if( p->pStatement ) nRet = p->pStatement->iId+1;
! 8593: return nRet;
! 8594: }
! 8595:
! 8596: /*
! 8597: ** Return a component of the report.
! 8598: */
! 8599: const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
! 8600: const char *zRet = 0;
! 8601: IdxStatement *pStmt;
! 8602:
! 8603: if( p->bRun==0 ) return 0;
! 8604: for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
! 8605: switch( eReport ){
! 8606: case EXPERT_REPORT_SQL:
! 8607: if( pStmt ) zRet = pStmt->zSql;
! 8608: break;
! 8609: case EXPERT_REPORT_INDEXES:
! 8610: if( pStmt ) zRet = pStmt->zIdx;
! 8611: break;
! 8612: case EXPERT_REPORT_PLAN:
! 8613: if( pStmt ) zRet = pStmt->zEQP;
! 8614: break;
! 8615: case EXPERT_REPORT_CANDIDATES:
! 8616: zRet = p->zCandidates;
! 8617: break;
! 8618: }
! 8619: return zRet;
! 8620: }
! 8621:
! 8622: /*
! 8623: ** Free an sqlite3expert object.
! 8624: */
! 8625: void sqlite3_expert_destroy(sqlite3expert *p){
! 8626: if( p ){
! 8627: sqlite3_close(p->dbm);
! 8628: sqlite3_close(p->dbv);
! 8629: idxScanFree(p->pScan, 0);
! 8630: idxStatementFree(p->pStatement, 0);
! 8631: idxTableFree(p->pTable);
! 8632: idxWriteFree(p->pWrite);
! 8633: idxHashClear(&p->hIdx);
! 8634: sqlite3_free(p->zCandidates);
! 8635: sqlite3_free(p);
! 8636: }
! 8637: }
! 8638:
! 8639: #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
! 8640:
! 8641: /************************* End ../ext/expert/sqlite3expert.c ********************/
! 8642:
! 8643: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 8644: /************************* Begin ../ext/misc/dbdata.c ******************/
! 8645: /*
! 8646: ** 2019-04-17
! 8647: **
! 8648: ** The author disclaims copyright to this source code. In place of
! 8649: ** a legal notice, here is a blessing:
! 8650: **
! 8651: ** May you do good and not evil.
! 8652: ** May you find forgiveness for yourself and forgive others.
! 8653: ** May you share freely, never taking more than you give.
! 8654: **
! 8655: ******************************************************************************
! 8656: **
! 8657: ** This file contains an implementation of two eponymous virtual tables,
! 8658: ** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
! 8659: ** "sqlite_dbpage" eponymous virtual table be available.
! 8660: **
! 8661: ** SQLITE_DBDATA:
! 8662: ** sqlite_dbdata is used to extract data directly from a database b-tree
! 8663: ** page and its associated overflow pages, bypassing the b-tree layer.
! 8664: ** The table schema is equivalent to:
! 8665: **
! 8666: ** CREATE TABLE sqlite_dbdata(
! 8667: ** pgno INTEGER,
! 8668: ** cell INTEGER,
! 8669: ** field INTEGER,
! 8670: ** value ANY,
! 8671: ** schema TEXT HIDDEN
! 8672: ** );
! 8673: **
! 8674: ** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
! 8675: ** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
! 8676: ** "schema".
! 8677: **
! 8678: ** Each page of the database is inspected. If it cannot be interpreted as
! 8679: ** a b-tree page, or if it is a b-tree page containing 0 entries, the
! 8680: ** sqlite_dbdata table contains no rows for that page. Otherwise, the
! 8681: ** table contains one row for each field in the record associated with
! 8682: ** each cell on the page. For intkey b-trees, the key value is stored in
! 8683: ** field -1.
! 8684: **
! 8685: ** For example, for the database:
! 8686: **
! 8687: ** CREATE TABLE t1(a, b); -- root page is page 2
! 8688: ** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
! 8689: ** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
! 8690: **
! 8691: ** the sqlite_dbdata table contains, as well as from entries related to
! 8692: ** page 1, content equivalent to:
! 8693: **
! 8694: ** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
! 8695: ** (2, 0, -1, 5 ),
! 8696: ** (2, 0, 0, 'v' ),
! 8697: ** (2, 0, 1, 'five'),
! 8698: ** (2, 1, -1, 10 ),
! 8699: ** (2, 1, 0, 'x' ),
! 8700: ** (2, 1, 1, 'ten' );
! 8701: **
! 8702: ** If database corruption is encountered, this module does not report an
! 8703: ** error. Instead, it attempts to extract as much data as possible and
! 8704: ** ignores the corruption.
! 8705: **
! 8706: ** SQLITE_DBPTR:
! 8707: ** The sqlite_dbptr table has the following schema:
! 8708: **
! 8709: ** CREATE TABLE sqlite_dbptr(
! 8710: ** pgno INTEGER,
! 8711: ** child INTEGER,
! 8712: ** schema TEXT HIDDEN
! 8713: ** );
! 8714: **
! 8715: ** It contains one entry for each b-tree pointer between a parent and
! 8716: ** child page in the database.
! 8717: */
! 8718: #if !defined(SQLITEINT_H)
! 8719: /* #include "sqlite3ext.h" */
! 8720:
! 8721: /* typedef unsigned char u8; */
! 8722:
! 8723: #endif
! 8724: SQLITE_EXTENSION_INIT1
! 8725: #include <string.h>
! 8726: #include <assert.h>
! 8727:
! 8728: #define DBDATA_PADDING_BYTES 100
! 8729:
! 8730: typedef struct DbdataTable DbdataTable;
! 8731: typedef struct DbdataCursor DbdataCursor;
! 8732:
! 8733: /* Cursor object */
! 8734: struct DbdataCursor {
! 8735: sqlite3_vtab_cursor base; /* Base class. Must be first */
! 8736: sqlite3_stmt *pStmt; /* For fetching database pages */
! 8737:
! 8738: int iPgno; /* Current page number */
! 8739: u8 *aPage; /* Buffer containing page */
! 8740: int nPage; /* Size of aPage[] in bytes */
! 8741: int nCell; /* Number of cells on aPage[] */
! 8742: int iCell; /* Current cell number */
! 8743: int bOnePage; /* True to stop after one page */
! 8744: int szDb;
! 8745: sqlite3_int64 iRowid;
! 8746:
! 8747: /* Only for the sqlite_dbdata table */
! 8748: u8 *pRec; /* Buffer containing current record */
! 8749: int nRec; /* Size of pRec[] in bytes */
! 8750: int nHdr; /* Size of header in bytes */
! 8751: int iField; /* Current field number */
! 8752: u8 *pHdrPtr;
! 8753: u8 *pPtr;
! 8754:
! 8755: sqlite3_int64 iIntkey; /* Integer key value */
! 8756: };
! 8757:
! 8758: /* Table object */
! 8759: struct DbdataTable {
! 8760: sqlite3_vtab base; /* Base class. Must be first */
! 8761: sqlite3 *db; /* The database connection */
! 8762: sqlite3_stmt *pStmt; /* For fetching database pages */
! 8763: int bPtr; /* True for sqlite3_dbptr table */
! 8764: };
! 8765:
! 8766: /* Column and schema definitions for sqlite_dbdata */
! 8767: #define DBDATA_COLUMN_PGNO 0
! 8768: #define DBDATA_COLUMN_CELL 1
! 8769: #define DBDATA_COLUMN_FIELD 2
! 8770: #define DBDATA_COLUMN_VALUE 3
! 8771: #define DBDATA_COLUMN_SCHEMA 4
! 8772: #define DBDATA_SCHEMA \
! 8773: "CREATE TABLE x(" \
! 8774: " pgno INTEGER," \
! 8775: " cell INTEGER," \
! 8776: " field INTEGER," \
! 8777: " value ANY," \
! 8778: " schema TEXT HIDDEN" \
! 8779: ")"
! 8780:
! 8781: /* Column and schema definitions for sqlite_dbptr */
! 8782: #define DBPTR_COLUMN_PGNO 0
! 8783: #define DBPTR_COLUMN_CHILD 1
! 8784: #define DBPTR_COLUMN_SCHEMA 2
! 8785: #define DBPTR_SCHEMA \
! 8786: "CREATE TABLE x(" \
! 8787: " pgno INTEGER," \
! 8788: " child INTEGER," \
! 8789: " schema TEXT HIDDEN" \
! 8790: ")"
! 8791:
! 8792: /*
! 8793: ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
! 8794: ** table.
! 8795: */
! 8796: static int dbdataConnect(
! 8797: sqlite3 *db,
! 8798: void *pAux,
! 8799: int argc, const char *const*argv,
! 8800: sqlite3_vtab **ppVtab,
! 8801: char **pzErr
! 8802: ){
! 8803: DbdataTable *pTab = 0;
! 8804: int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
! 8805:
! 8806: if( rc==SQLITE_OK ){
! 8807: pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
! 8808: if( pTab==0 ){
! 8809: rc = SQLITE_NOMEM;
! 8810: }else{
! 8811: memset(pTab, 0, sizeof(DbdataTable));
! 8812: pTab->db = db;
! 8813: pTab->bPtr = (pAux!=0);
! 8814: }
! 8815: }
! 8816:
! 8817: *ppVtab = (sqlite3_vtab*)pTab;
! 8818: return rc;
! 8819: }
! 8820:
! 8821: /*
! 8822: ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
! 8823: */
! 8824: static int dbdataDisconnect(sqlite3_vtab *pVtab){
! 8825: DbdataTable *pTab = (DbdataTable*)pVtab;
! 8826: if( pTab ){
! 8827: sqlite3_finalize(pTab->pStmt);
! 8828: sqlite3_free(pVtab);
! 8829: }
! 8830: return SQLITE_OK;
! 8831: }
! 8832:
! 8833: /*
! 8834: ** This function interprets two types of constraints:
! 8835: **
! 8836: ** schema=?
! 8837: ** pgno=?
! 8838: **
! 8839: ** If neither are present, idxNum is set to 0. If schema=? is present,
! 8840: ** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
! 8841: ** in idxNum is set.
! 8842: **
! 8843: ** If both parameters are present, schema is in position 0 and pgno in
! 8844: ** position 1.
! 8845: */
! 8846: static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
! 8847: DbdataTable *pTab = (DbdataTable*)tab;
! 8848: int i;
! 8849: int iSchema = -1;
! 8850: int iPgno = -1;
! 8851: int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
! 8852:
! 8853: for(i=0; i<pIdx->nConstraint; i++){
! 8854: struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
! 8855: if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 8856: if( p->iColumn==colSchema ){
! 8857: if( p->usable==0 ) return SQLITE_CONSTRAINT;
! 8858: iSchema = i;
! 8859: }
! 8860: if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
! 8861: iPgno = i;
! 8862: }
! 8863: }
! 8864: }
! 8865:
! 8866: if( iSchema>=0 ){
! 8867: pIdx->aConstraintUsage[iSchema].argvIndex = 1;
! 8868: pIdx->aConstraintUsage[iSchema].omit = 1;
! 8869: }
! 8870: if( iPgno>=0 ){
! 8871: pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
! 8872: pIdx->aConstraintUsage[iPgno].omit = 1;
! 8873: pIdx->estimatedCost = 100;
! 8874: pIdx->estimatedRows = 50;
! 8875:
! 8876: if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
! 8877: int iCol = pIdx->aOrderBy[0].iColumn;
! 8878: if( pIdx->nOrderBy==1 ){
! 8879: pIdx->orderByConsumed = (iCol==0 || iCol==1);
! 8880: }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
! 8881: pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
! 8882: }
! 8883: }
! 8884:
! 8885: }else{
! 8886: pIdx->estimatedCost = 100000000;
! 8887: pIdx->estimatedRows = 1000000000;
! 8888: }
! 8889: pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
! 8890: return SQLITE_OK;
! 8891: }
! 8892:
! 8893: /*
! 8894: ** Open a new sqlite_dbdata or sqlite_dbptr cursor.
! 8895: */
! 8896: static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
! 8897: DbdataCursor *pCsr;
! 8898:
! 8899: pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
! 8900: if( pCsr==0 ){
! 8901: return SQLITE_NOMEM;
! 8902: }else{
! 8903: memset(pCsr, 0, sizeof(DbdataCursor));
! 8904: pCsr->base.pVtab = pVTab;
! 8905: }
! 8906:
! 8907: *ppCursor = (sqlite3_vtab_cursor *)pCsr;
! 8908: return SQLITE_OK;
! 8909: }
! 8910:
! 8911: /*
! 8912: ** Restore a cursor object to the state it was in when first allocated
! 8913: ** by dbdataOpen().
! 8914: */
! 8915: static void dbdataResetCursor(DbdataCursor *pCsr){
! 8916: DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
! 8917: if( pTab->pStmt==0 ){
! 8918: pTab->pStmt = pCsr->pStmt;
! 8919: }else{
! 8920: sqlite3_finalize(pCsr->pStmt);
! 8921: }
! 8922: pCsr->pStmt = 0;
! 8923: pCsr->iPgno = 1;
! 8924: pCsr->iCell = 0;
! 8925: pCsr->iField = 0;
! 8926: pCsr->bOnePage = 0;
! 8927: sqlite3_free(pCsr->aPage);
! 8928: sqlite3_free(pCsr->pRec);
! 8929: pCsr->pRec = 0;
! 8930: pCsr->aPage = 0;
! 8931: }
! 8932:
! 8933: /*
! 8934: ** Close an sqlite_dbdata or sqlite_dbptr cursor.
! 8935: */
! 8936: static int dbdataClose(sqlite3_vtab_cursor *pCursor){
! 8937: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 8938: dbdataResetCursor(pCsr);
! 8939: sqlite3_free(pCsr);
! 8940: return SQLITE_OK;
! 8941: }
! 8942:
! 8943: /*
! 8944: ** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
! 8945: */
! 8946: static unsigned int get_uint16(unsigned char *a){
! 8947: return (a[0]<<8)|a[1];
! 8948: }
! 8949: static unsigned int get_uint32(unsigned char *a){
! 8950: return ((unsigned int)a[0]<<24)
! 8951: | ((unsigned int)a[1]<<16)
! 8952: | ((unsigned int)a[2]<<8)
! 8953: | ((unsigned int)a[3]);
! 8954: }
! 8955:
! 8956: /*
! 8957: ** Load page pgno from the database via the sqlite_dbpage virtual table.
! 8958: ** If successful, set (*ppPage) to point to a buffer containing the page
! 8959: ** data, (*pnPage) to the size of that buffer in bytes and return
! 8960: ** SQLITE_OK. In this case it is the responsibility of the caller to
! 8961: ** eventually free the buffer using sqlite3_free().
! 8962: **
! 8963: ** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
! 8964: ** return an SQLite error code.
! 8965: */
! 8966: static int dbdataLoadPage(
! 8967: DbdataCursor *pCsr, /* Cursor object */
! 8968: unsigned int pgno, /* Page number of page to load */
! 8969: u8 **ppPage, /* OUT: pointer to page buffer */
! 8970: int *pnPage /* OUT: Size of (*ppPage) in bytes */
! 8971: ){
! 8972: int rc2;
! 8973: int rc = SQLITE_OK;
! 8974: sqlite3_stmt *pStmt = pCsr->pStmt;
! 8975:
! 8976: *ppPage = 0;
! 8977: *pnPage = 0;
! 8978: sqlite3_bind_int64(pStmt, 2, pgno);
! 8979: if( SQLITE_ROW==sqlite3_step(pStmt) ){
! 8980: int nCopy = sqlite3_column_bytes(pStmt, 0);
! 8981: if( nCopy>0 ){
! 8982: u8 *pPage;
! 8983: pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
! 8984: if( pPage==0 ){
! 8985: rc = SQLITE_NOMEM;
! 8986: }else{
! 8987: const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
! 8988: memcpy(pPage, pCopy, nCopy);
! 8989: memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
! 8990: }
! 8991: *ppPage = pPage;
! 8992: *pnPage = nCopy;
! 8993: }
! 8994: }
! 8995: rc2 = sqlite3_reset(pStmt);
! 8996: if( rc==SQLITE_OK ) rc = rc2;
! 8997:
! 8998: return rc;
! 8999: }
! 9000:
! 9001: /*
! 9002: ** Read a varint. Put the value in *pVal and return the number of bytes.
! 9003: */
! 9004: static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
! 9005: sqlite3_int64 v = 0;
! 9006: int i;
! 9007: for(i=0; i<8; i++){
! 9008: v = (v<<7) + (z[i]&0x7f);
! 9009: if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
! 9010: }
! 9011: v = (v<<8) + (z[i]&0xff);
! 9012: *pVal = v;
! 9013: return 9;
! 9014: }
! 9015:
! 9016: /*
! 9017: ** Return the number of bytes of space used by an SQLite value of type
! 9018: ** eType.
! 9019: */
! 9020: static int dbdataValueBytes(int eType){
! 9021: switch( eType ){
! 9022: case 0: case 8: case 9:
! 9023: case 10: case 11:
! 9024: return 0;
! 9025: case 1:
! 9026: return 1;
! 9027: case 2:
! 9028: return 2;
! 9029: case 3:
! 9030: return 3;
! 9031: case 4:
! 9032: return 4;
! 9033: case 5:
! 9034: return 6;
! 9035: case 6:
! 9036: case 7:
! 9037: return 8;
! 9038: default:
! 9039: if( eType>0 ){
! 9040: return ((eType-12) / 2);
! 9041: }
! 9042: return 0;
! 9043: }
! 9044: }
! 9045:
! 9046: /*
! 9047: ** Load a value of type eType from buffer pData and use it to set the
! 9048: ** result of context object pCtx.
! 9049: */
! 9050: static void dbdataValue(
! 9051: sqlite3_context *pCtx,
! 9052: int eType,
! 9053: u8 *pData,
! 9054: int nData
! 9055: ){
! 9056: if( eType>=0 && dbdataValueBytes(eType)<=nData ){
! 9057: switch( eType ){
! 9058: case 0:
! 9059: case 10:
! 9060: case 11:
! 9061: sqlite3_result_null(pCtx);
! 9062: break;
! 9063:
! 9064: case 8:
! 9065: sqlite3_result_int(pCtx, 0);
! 9066: break;
! 9067: case 9:
! 9068: sqlite3_result_int(pCtx, 1);
! 9069: break;
! 9070:
! 9071: case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
! 9072: sqlite3_uint64 v = (signed char)pData[0];
! 9073: pData++;
! 9074: switch( eType ){
! 9075: case 7:
! 9076: case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
! 9077: case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
! 9078: case 4: v = (v<<8) + pData[0]; pData++;
! 9079: case 3: v = (v<<8) + pData[0]; pData++;
! 9080: case 2: v = (v<<8) + pData[0]; pData++;
! 9081: }
! 9082:
! 9083: if( eType==7 ){
! 9084: double r;
! 9085: memcpy(&r, &v, sizeof(r));
! 9086: sqlite3_result_double(pCtx, r);
! 9087: }else{
! 9088: sqlite3_result_int64(pCtx, (sqlite3_int64)v);
! 9089: }
! 9090: break;
! 9091: }
! 9092:
! 9093: default: {
! 9094: int n = ((eType-12) / 2);
! 9095: if( eType % 2 ){
! 9096: sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
! 9097: }else{
! 9098: sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
! 9099: }
! 9100: }
! 9101: }
! 9102: }
! 9103: }
! 9104:
! 9105: /*
! 9106: ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
! 9107: */
! 9108: static int dbdataNext(sqlite3_vtab_cursor *pCursor){
! 9109: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 9110: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
! 9111:
! 9112: pCsr->iRowid++;
! 9113: while( 1 ){
! 9114: int rc;
! 9115: int iOff = (pCsr->iPgno==1 ? 100 : 0);
! 9116: int bNextPage = 0;
! 9117:
! 9118: if( pCsr->aPage==0 ){
! 9119: while( 1 ){
! 9120: if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
! 9121: rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
! 9122: if( rc!=SQLITE_OK ) return rc;
! 9123: if( pCsr->aPage ) break;
! 9124: pCsr->iPgno++;
! 9125: }
! 9126: pCsr->iCell = pTab->bPtr ? -2 : 0;
! 9127: pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
! 9128: }
! 9129:
! 9130: if( pTab->bPtr ){
! 9131: if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
! 9132: pCsr->iCell = pCsr->nCell;
! 9133: }
! 9134: pCsr->iCell++;
! 9135: if( pCsr->iCell>=pCsr->nCell ){
! 9136: sqlite3_free(pCsr->aPage);
! 9137: pCsr->aPage = 0;
! 9138: if( pCsr->bOnePage ) return SQLITE_OK;
! 9139: pCsr->iPgno++;
! 9140: }else{
! 9141: return SQLITE_OK;
! 9142: }
! 9143: }else{
! 9144: /* If there is no record loaded, load it now. */
! 9145: if( pCsr->pRec==0 ){
! 9146: int bHasRowid = 0;
! 9147: int nPointer = 0;
! 9148: sqlite3_int64 nPayload = 0;
! 9149: sqlite3_int64 nHdr = 0;
! 9150: int iHdr;
! 9151: int U, X;
! 9152: int nLocal;
! 9153:
! 9154: switch( pCsr->aPage[iOff] ){
! 9155: case 0x02:
! 9156: nPointer = 4;
! 9157: break;
! 9158: case 0x0a:
! 9159: break;
! 9160: case 0x0d:
! 9161: bHasRowid = 1;
! 9162: break;
! 9163: default:
! 9164: /* This is not a b-tree page with records on it. Continue. */
! 9165: pCsr->iCell = pCsr->nCell;
! 9166: break;
! 9167: }
! 9168:
! 9169: if( pCsr->iCell>=pCsr->nCell ){
! 9170: bNextPage = 1;
! 9171: }else{
! 9172:
! 9173: iOff += 8 + nPointer + pCsr->iCell*2;
! 9174: if( iOff>pCsr->nPage ){
! 9175: bNextPage = 1;
! 9176: }else{
! 9177: iOff = get_uint16(&pCsr->aPage[iOff]);
! 9178: }
! 9179:
! 9180: /* For an interior node cell, skip past the child-page number */
! 9181: iOff += nPointer;
! 9182:
! 9183: /* Load the "byte of payload including overflow" field */
! 9184: if( bNextPage || iOff>pCsr->nPage ){
! 9185: bNextPage = 1;
! 9186: }else{
! 9187: iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
! 9188: }
! 9189:
! 9190: /* If this is a leaf intkey cell, load the rowid */
! 9191: if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
! 9192: iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
! 9193: }
! 9194:
! 9195: /* Figure out how much data to read from the local page */
! 9196: U = pCsr->nPage;
! 9197: if( bHasRowid ){
! 9198: X = U-35;
! 9199: }else{
! 9200: X = ((U-12)*64/255)-23;
! 9201: }
! 9202: if( nPayload<=X ){
! 9203: nLocal = nPayload;
! 9204: }else{
! 9205: int M, K;
! 9206: M = ((U-12)*32/255)-23;
! 9207: K = M+((nPayload-M)%(U-4));
! 9208: if( K<=X ){
! 9209: nLocal = K;
! 9210: }else{
! 9211: nLocal = M;
! 9212: }
! 9213: }
! 9214:
! 9215: if( bNextPage || nLocal+iOff>pCsr->nPage ){
! 9216: bNextPage = 1;
! 9217: }else{
! 9218:
! 9219: /* Allocate space for payload. And a bit more to catch small buffer
! 9220: ** overruns caused by attempting to read a varint or similar from
! 9221: ** near the end of a corrupt record. */
! 9222: pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
! 9223: if( pCsr->pRec==0 ) return SQLITE_NOMEM;
! 9224: memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
! 9225: pCsr->nRec = nPayload;
! 9226:
! 9227: /* Load the nLocal bytes of payload */
! 9228: memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
! 9229: iOff += nLocal;
! 9230:
! 9231: /* Load content from overflow pages */
! 9232: if( nPayload>nLocal ){
! 9233: sqlite3_int64 nRem = nPayload - nLocal;
! 9234: unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
! 9235: while( nRem>0 ){
! 9236: u8 *aOvfl = 0;
! 9237: int nOvfl = 0;
! 9238: int nCopy;
! 9239: rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
! 9240: assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
! 9241: if( rc!=SQLITE_OK ) return rc;
! 9242: if( aOvfl==0 ) break;
! 9243:
! 9244: nCopy = U-4;
! 9245: if( nCopy>nRem ) nCopy = nRem;
! 9246: memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
! 9247: nRem -= nCopy;
! 9248:
! 9249: pgnoOvfl = get_uint32(aOvfl);
! 9250: sqlite3_free(aOvfl);
! 9251: }
! 9252: }
! 9253:
! 9254: iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
! 9255: pCsr->nHdr = nHdr;
! 9256: pCsr->pHdrPtr = &pCsr->pRec[iHdr];
! 9257: pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
! 9258: pCsr->iField = (bHasRowid ? -1 : 0);
! 9259: }
! 9260: }
! 9261: }else{
! 9262: pCsr->iField++;
! 9263: if( pCsr->iField>0 ){
! 9264: sqlite3_int64 iType;
! 9265: if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
! 9266: bNextPage = 1;
! 9267: }else{
! 9268: pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
! 9269: pCsr->pPtr += dbdataValueBytes(iType);
! 9270: }
! 9271: }
! 9272: }
! 9273:
! 9274: if( bNextPage ){
! 9275: sqlite3_free(pCsr->aPage);
! 9276: sqlite3_free(pCsr->pRec);
! 9277: pCsr->aPage = 0;
! 9278: pCsr->pRec = 0;
! 9279: if( pCsr->bOnePage ) return SQLITE_OK;
! 9280: pCsr->iPgno++;
! 9281: }else{
! 9282: if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
! 9283: return SQLITE_OK;
! 9284: }
! 9285:
! 9286: /* Advance to the next cell. The next iteration of the loop will load
! 9287: ** the record and so on. */
! 9288: sqlite3_free(pCsr->pRec);
! 9289: pCsr->pRec = 0;
! 9290: pCsr->iCell++;
! 9291: }
! 9292: }
! 9293: }
! 9294:
! 9295: assert( !"can't get here" );
! 9296: return SQLITE_OK;
! 9297: }
! 9298:
! 9299: /*
! 9300: ** Return true if the cursor is at EOF.
! 9301: */
! 9302: static int dbdataEof(sqlite3_vtab_cursor *pCursor){
! 9303: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 9304: return pCsr->aPage==0;
! 9305: }
! 9306:
! 9307: /*
! 9308: ** Determine the size in pages of database zSchema (where zSchema is
! 9309: ** "main", "temp" or the name of an attached database) and set
! 9310: ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
! 9311: ** an SQLite error code.
! 9312: */
! 9313: static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
! 9314: DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
! 9315: char *zSql = 0;
! 9316: int rc, rc2;
! 9317: sqlite3_stmt *pStmt = 0;
! 9318:
! 9319: zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
! 9320: if( zSql==0 ) return SQLITE_NOMEM;
! 9321: rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
! 9322: sqlite3_free(zSql);
! 9323: if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
! 9324: pCsr->szDb = sqlite3_column_int(pStmt, 0);
! 9325: }
! 9326: rc2 = sqlite3_finalize(pStmt);
! 9327: if( rc==SQLITE_OK ) rc = rc2;
! 9328: return rc;
! 9329: }
! 9330:
! 9331: /*
! 9332: ** xFilter method for sqlite_dbdata and sqlite_dbptr.
! 9333: */
! 9334: static int dbdataFilter(
! 9335: sqlite3_vtab_cursor *pCursor,
! 9336: int idxNum, const char *idxStr,
! 9337: int argc, sqlite3_value **argv
! 9338: ){
! 9339: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 9340: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
! 9341: int rc = SQLITE_OK;
! 9342: const char *zSchema = "main";
! 9343:
! 9344: dbdataResetCursor(pCsr);
! 9345: assert( pCsr->iPgno==1 );
! 9346: if( idxNum & 0x01 ){
! 9347: zSchema = (const char*)sqlite3_value_text(argv[0]);
! 9348: }
! 9349: if( idxNum & 0x02 ){
! 9350: pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
! 9351: pCsr->bOnePage = 1;
! 9352: }else{
! 9353: pCsr->nPage = dbdataDbsize(pCsr, zSchema);
! 9354: rc = dbdataDbsize(pCsr, zSchema);
! 9355: }
! 9356:
! 9357: if( rc==SQLITE_OK ){
! 9358: if( pTab->pStmt ){
! 9359: pCsr->pStmt = pTab->pStmt;
! 9360: pTab->pStmt = 0;
! 9361: }else{
! 9362: rc = sqlite3_prepare_v2(pTab->db,
! 9363: "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
! 9364: &pCsr->pStmt, 0
! 9365: );
! 9366: }
! 9367: }
! 9368: if( rc==SQLITE_OK ){
! 9369: rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
! 9370: }else{
! 9371: pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
! 9372: }
! 9373: if( rc==SQLITE_OK ){
! 9374: rc = dbdataNext(pCursor);
! 9375: }
! 9376: return rc;
! 9377: }
! 9378:
! 9379: /*
! 9380: ** Return a column for the sqlite_dbdata or sqlite_dbptr table.
! 9381: */
! 9382: static int dbdataColumn(
! 9383: sqlite3_vtab_cursor *pCursor,
! 9384: sqlite3_context *ctx,
! 9385: int i
! 9386: ){
! 9387: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 9388: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
! 9389: if( pTab->bPtr ){
! 9390: switch( i ){
! 9391: case DBPTR_COLUMN_PGNO:
! 9392: sqlite3_result_int64(ctx, pCsr->iPgno);
! 9393: break;
! 9394: case DBPTR_COLUMN_CHILD: {
! 9395: int iOff = pCsr->iPgno==1 ? 100 : 0;
! 9396: if( pCsr->iCell<0 ){
! 9397: iOff += 8;
! 9398: }else{
! 9399: iOff += 12 + pCsr->iCell*2;
! 9400: if( iOff>pCsr->nPage ) return SQLITE_OK;
! 9401: iOff = get_uint16(&pCsr->aPage[iOff]);
! 9402: }
! 9403: if( iOff<=pCsr->nPage ){
! 9404: sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
! 9405: }
! 9406: break;
! 9407: }
! 9408: }
! 9409: }else{
! 9410: switch( i ){
! 9411: case DBDATA_COLUMN_PGNO:
! 9412: sqlite3_result_int64(ctx, pCsr->iPgno);
! 9413: break;
! 9414: case DBDATA_COLUMN_CELL:
! 9415: sqlite3_result_int(ctx, pCsr->iCell);
! 9416: break;
! 9417: case DBDATA_COLUMN_FIELD:
! 9418: sqlite3_result_int(ctx, pCsr->iField);
! 9419: break;
! 9420: case DBDATA_COLUMN_VALUE: {
! 9421: if( pCsr->iField<0 ){
! 9422: sqlite3_result_int64(ctx, pCsr->iIntkey);
! 9423: }else{
! 9424: sqlite3_int64 iType;
! 9425: dbdataGetVarint(pCsr->pHdrPtr, &iType);
! 9426: dbdataValue(
! 9427: ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
! 9428: );
! 9429: }
! 9430: break;
! 9431: }
! 9432: }
! 9433: }
! 9434: return SQLITE_OK;
! 9435: }
! 9436:
! 9437: /*
! 9438: ** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
! 9439: */
! 9440: static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
! 9441: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 9442: *pRowid = pCsr->iRowid;
! 9443: return SQLITE_OK;
! 9444: }
! 9445:
! 9446:
! 9447: /*
! 9448: ** Invoke this routine to register the "sqlite_dbdata" virtual table module
! 9449: */
! 9450: static int sqlite3DbdataRegister(sqlite3 *db){
! 9451: static sqlite3_module dbdata_module = {
! 9452: 0, /* iVersion */
! 9453: 0, /* xCreate */
! 9454: dbdataConnect, /* xConnect */
! 9455: dbdataBestIndex, /* xBestIndex */
! 9456: dbdataDisconnect, /* xDisconnect */
! 9457: 0, /* xDestroy */
! 9458: dbdataOpen, /* xOpen - open a cursor */
! 9459: dbdataClose, /* xClose - close a cursor */
! 9460: dbdataFilter, /* xFilter - configure scan constraints */
! 9461: dbdataNext, /* xNext - advance a cursor */
! 9462: dbdataEof, /* xEof - check for end of scan */
! 9463: dbdataColumn, /* xColumn - read data */
! 9464: dbdataRowid, /* xRowid - read data */
! 9465: 0, /* xUpdate */
! 9466: 0, /* xBegin */
! 9467: 0, /* xSync */
! 9468: 0, /* xCommit */
! 9469: 0, /* xRollback */
! 9470: 0, /* xFindMethod */
! 9471: 0, /* xRename */
! 9472: 0, /* xSavepoint */
! 9473: 0, /* xRelease */
! 9474: 0, /* xRollbackTo */
! 9475: 0 /* xShadowName */
! 9476: };
! 9477:
! 9478: int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
! 9479: if( rc==SQLITE_OK ){
! 9480: rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
! 9481: }
! 9482: return rc;
! 9483: }
! 9484:
! 9485: #ifdef _WIN32
! 9486:
! 9487: #endif
! 9488: int sqlite3_dbdata_init(
! 9489: sqlite3 *db,
! 9490: char **pzErrMsg,
! 9491: const sqlite3_api_routines *pApi
! 9492: ){
! 9493: SQLITE_EXTENSION_INIT2(pApi);
! 9494: return sqlite3DbdataRegister(db);
! 9495: }
! 9496:
! 9497: /************************* End ../ext/misc/dbdata.c ********************/
! 9498: #endif
! 9499:
! 9500: #if defined(SQLITE_ENABLE_SESSION)
! 9501: /*
! 9502: ** State information for a single open session
! 9503: */
! 9504: typedef struct OpenSession OpenSession;
! 9505: struct OpenSession {
! 9506: char *zName; /* Symbolic name for this session */
! 9507: int nFilter; /* Number of xFilter rejection GLOB patterns */
! 9508: char **azFilter; /* Array of xFilter rejection GLOB patterns */
! 9509: sqlite3_session *p; /* The open session */
! 9510: };
! 9511: #endif
! 9512:
! 9513: /*
! 9514: ** Shell output mode information from before ".explain on",
! 9515: ** saved so that it can be restored by ".explain off"
! 9516: */
! 9517: typedef struct SavedModeInfo SavedModeInfo;
! 9518: struct SavedModeInfo {
! 9519: int valid; /* Is there legit data in here? */
! 9520: int mode; /* Mode prior to ".explain on" */
! 9521: int showHeader; /* The ".header" setting prior to ".explain on" */
! 9522: int colWidth[100]; /* Column widths prior to ".explain on" */
! 9523: };
! 9524:
! 9525: typedef struct ExpertInfo ExpertInfo;
! 9526: struct ExpertInfo {
! 9527: sqlite3expert *pExpert;
! 9528: int bVerbose;
! 9529: };
! 9530:
! 9531: /* A single line in the EQP output */
! 9532: typedef struct EQPGraphRow EQPGraphRow;
! 9533: struct EQPGraphRow {
! 9534: int iEqpId; /* ID for this row */
! 9535: int iParentId; /* ID of the parent row */
! 9536: EQPGraphRow *pNext; /* Next row in sequence */
! 9537: char zText[1]; /* Text to display for this row */
! 9538: };
! 9539:
! 9540: /* All EQP output is collected into an instance of the following */
! 9541: typedef struct EQPGraph EQPGraph;
! 9542: struct EQPGraph {
! 9543: EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
! 9544: EQPGraphRow *pLast; /* Last element of the pRow list */
! 9545: char zPrefix[100]; /* Graph prefix */
! 9546: };
! 9547:
! 9548: /*
! 9549: ** State information about the database connection is contained in an
! 9550: ** instance of the following structure.
! 9551: */
! 9552: typedef struct ShellState ShellState;
! 9553: struct ShellState {
! 9554: sqlite3 *db; /* The database */
! 9555: u8 autoExplain; /* Automatically turn on .explain mode */
! 9556: u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
! 9557: u8 autoEQPtest; /* autoEQP is in test mode */
! 9558: u8 autoEQPtrace; /* autoEQP is in trace mode */
! 9559: u8 statsOn; /* True to display memory stats before each finalize */
! 9560: u8 scanstatsOn; /* True to display scan stats before each finalize */
! 9561: u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
! 9562: u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
! 9563: u8 nEqpLevel; /* Depth of the EQP output graph */
! 9564: u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
! 9565: unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
! 9566: int outCount; /* Revert to stdout when reaching zero */
! 9567: int cnt; /* Number of records displayed so far */
! 9568: int lineno; /* Line number of last line read from in */
! 9569: FILE *in; /* Read commands from this stream */
! 9570: FILE *out; /* Write results here */
! 9571: FILE *traceOut; /* Output for sqlite3_trace() */
! 9572: int nErr; /* Number of errors seen */
! 9573: int mode; /* An output mode setting */
! 9574: int modePrior; /* Saved mode */
! 9575: int cMode; /* temporary output mode for the current query */
! 9576: int normalMode; /* Output mode before ".explain on" */
! 9577: int writableSchema; /* True if PRAGMA writable_schema=ON */
! 9578: int showHeader; /* True to show column names in List or Column mode */
! 9579: int nCheck; /* Number of ".check" commands run */
! 9580: unsigned nProgress; /* Number of progress callbacks encountered */
! 9581: unsigned mxProgress; /* Maximum progress callbacks before failing */
! 9582: unsigned flgProgress; /* Flags for the progress callback */
! 9583: unsigned shellFlgs; /* Various flags */
! 9584: sqlite3_int64 szMax; /* --maxsize argument to .open */
! 9585: char *zDestTable; /* Name of destination table when MODE_Insert */
! 9586: char *zTempFile; /* Temporary file that might need deleting */
! 9587: char zTestcase[30]; /* Name of current test case */
! 9588: char colSeparator[20]; /* Column separator character for several modes */
! 9589: char rowSeparator[20]; /* Row separator character for MODE_Ascii */
! 9590: char colSepPrior[20]; /* Saved column separator */
! 9591: char rowSepPrior[20]; /* Saved row separator */
! 9592: int colWidth[100]; /* Requested width of each column when in column mode*/
! 9593: int actualWidth[100]; /* Actual width of each column */
! 9594: char nullValue[20]; /* The text to print when a NULL comes back from
! 9595: ** the database */
! 9596: char outfile[FILENAME_MAX]; /* Filename for *out */
! 9597: const char *zDbFilename; /* name of the database file */
! 9598: char *zFreeOnClose; /* Filename to free when closing */
! 9599: const char *zVfs; /* Name of VFS to use */
! 9600: sqlite3_stmt *pStmt; /* Current statement if any. */
! 9601: FILE *pLog; /* Write log output here */
! 9602: int *aiIndent; /* Array of indents used in MODE_Explain */
! 9603: int nIndent; /* Size of array aiIndent[] */
! 9604: int iIndent; /* Index of current op in aiIndent[] */
! 9605: EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
! 9606: #if defined(SQLITE_ENABLE_SESSION)
! 9607: int nSession; /* Number of active sessions */
! 9608: OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
! 9609: #endif
! 9610: ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
! 9611: };
! 9612:
! 9613:
! 9614: /* Allowed values for ShellState.autoEQP
! 9615: */
! 9616: #define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
! 9617: #define AUTOEQP_on 1 /* Automatic EQP is on */
! 9618: #define AUTOEQP_trigger 2 /* On and also show plans for triggers */
! 9619: #define AUTOEQP_full 3 /* Show full EXPLAIN */
! 9620:
! 9621: /* Allowed values for ShellState.openMode
! 9622: */
! 9623: #define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
! 9624: #define SHELL_OPEN_NORMAL 1 /* Normal database file */
! 9625: #define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
! 9626: #define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
! 9627: #define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
! 9628: #define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
! 9629: #define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
! 9630:
! 9631: /* Allowed values for ShellState.eTraceType
! 9632: */
! 9633: #define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
! 9634: #define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
! 9635: #define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
! 9636:
! 9637: /* Bits in the ShellState.flgProgress variable */
! 9638: #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
! 9639: #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
! 9640: ** callback limit is reached, and for each
! 9641: ** top-level SQL statement */
! 9642: #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
! 9643:
! 9644: /*
! 9645: ** These are the allowed shellFlgs values
! 9646: */
! 9647: #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
! 9648: #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
! 9649: #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
! 9650: #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
! 9651: #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
! 9652: #define SHFLG_CountChanges 0x00000020 /* .changes setting */
! 9653: #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
! 9654:
! 9655: /*
! 9656: ** Macros for testing and setting shellFlgs
! 9657: */
! 9658: #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
! 9659: #define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
! 9660: #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
! 9661:
! 9662: /*
! 9663: ** These are the allowed modes.
! 9664: */
! 9665: #define MODE_Line 0 /* One column per line. Blank line between records */
! 9666: #define MODE_Column 1 /* One record per line in neat columns */
! 9667: #define MODE_List 2 /* One record per line with a separator */
! 9668: #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
! 9669: #define MODE_Html 4 /* Generate an XHTML table */
! 9670: #define MODE_Insert 5 /* Generate SQL "insert" statements */
! 9671: #define MODE_Quote 6 /* Quote values as for SQL */
! 9672: #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
! 9673: #define MODE_Csv 8 /* Quote strings, numbers are plain */
! 9674: #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
! 9675: #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
! 9676: #define MODE_Pretty 11 /* Pretty-print schemas */
! 9677: #define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
! 9678:
! 9679: static const char *modeDescr[] = {
! 9680: "line",
! 9681: "column",
! 9682: "list",
! 9683: "semi",
! 9684: "html",
! 9685: "insert",
! 9686: "quote",
! 9687: "tcl",
! 9688: "csv",
! 9689: "explain",
! 9690: "ascii",
! 9691: "prettyprint",
! 9692: "eqp"
! 9693: };
! 9694:
! 9695: /*
! 9696: ** These are the column/row/line separators used by the various
! 9697: ** import/export modes.
! 9698: */
! 9699: #define SEP_Column "|"
! 9700: #define SEP_Row "\n"
! 9701: #define SEP_Tab "\t"
! 9702: #define SEP_Space " "
! 9703: #define SEP_Comma ","
! 9704: #define SEP_CrLf "\r\n"
! 9705: #define SEP_Unit "\x1F"
! 9706: #define SEP_Record "\x1E"
! 9707:
! 9708: /*
! 9709: ** A callback for the sqlite3_log() interface.
! 9710: */
! 9711: static void shellLog(void *pArg, int iErrCode, const char *zMsg){
! 9712: ShellState *p = (ShellState*)pArg;
! 9713: if( p->pLog==0 ) return;
! 9714: utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
! 9715: fflush(p->pLog);
! 9716: }
! 9717:
! 9718: /*
! 9719: ** SQL function: shell_putsnl(X)
! 9720: **
! 9721: ** Write the text X to the screen (or whatever output is being directed)
! 9722: ** adding a newline at the end, and then return X.
! 9723: */
! 9724: static void shellPutsFunc(
! 9725: sqlite3_context *pCtx,
! 9726: int nVal,
! 9727: sqlite3_value **apVal
! 9728: ){
! 9729: ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
! 9730: (void)nVal;
! 9731: utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
! 9732: sqlite3_result_value(pCtx, apVal[0]);
! 9733: }
! 9734:
! 9735: /*
! 9736: ** SQL function: edit(VALUE)
! 9737: ** edit(VALUE,EDITOR)
! 9738: **
! 9739: ** These steps:
! 9740: **
! 9741: ** (1) Write VALUE into a temporary file.
! 9742: ** (2) Run program EDITOR on that temporary file.
! 9743: ** (3) Read the temporary file back and return its content as the result.
! 9744: ** (4) Delete the temporary file
! 9745: **
! 9746: ** If the EDITOR argument is omitted, use the value in the VISUAL
! 9747: ** environment variable. If still there is no EDITOR, through an error.
! 9748: **
! 9749: ** Also throw an error if the EDITOR program returns a non-zero exit code.
! 9750: */
! 9751: #ifndef SQLITE_NOHAVE_SYSTEM
! 9752: static void editFunc(
! 9753: sqlite3_context *context,
! 9754: int argc,
! 9755: sqlite3_value **argv
! 9756: ){
! 9757: const char *zEditor;
! 9758: char *zTempFile = 0;
! 9759: sqlite3 *db;
! 9760: char *zCmd = 0;
! 9761: int bBin;
! 9762: int rc;
! 9763: int hasCRNL = 0;
! 9764: FILE *f = 0;
! 9765: sqlite3_int64 sz;
! 9766: sqlite3_int64 x;
! 9767: unsigned char *p = 0;
! 9768:
! 9769: if( argc==2 ){
! 9770: zEditor = (const char*)sqlite3_value_text(argv[1]);
! 9771: }else{
! 9772: zEditor = getenv("VISUAL");
! 9773: }
! 9774: if( zEditor==0 ){
! 9775: sqlite3_result_error(context, "no editor for edit()", -1);
! 9776: return;
! 9777: }
! 9778: if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
! 9779: sqlite3_result_error(context, "NULL input to edit()", -1);
! 9780: return;
! 9781: }
! 9782: db = sqlite3_context_db_handle(context);
! 9783: zTempFile = 0;
! 9784: sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
! 9785: if( zTempFile==0 ){
! 9786: sqlite3_uint64 r = 0;
! 9787: sqlite3_randomness(sizeof(r), &r);
! 9788: zTempFile = sqlite3_mprintf("temp%llx", r);
! 9789: if( zTempFile==0 ){
! 9790: sqlite3_result_error_nomem(context);
! 9791: return;
! 9792: }
! 9793: }
! 9794: bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
! 9795: /* When writing the file to be edited, do \n to \r\n conversions on systems
! 9796: ** that want \r\n line endings */
! 9797: f = fopen(zTempFile, bBin ? "wb" : "w");
! 9798: if( f==0 ){
! 9799: sqlite3_result_error(context, "edit() cannot open temp file", -1);
! 9800: goto edit_func_end;
! 9801: }
! 9802: sz = sqlite3_value_bytes(argv[0]);
! 9803: if( bBin ){
! 9804: x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
! 9805: }else{
! 9806: const char *z = (const char*)sqlite3_value_text(argv[0]);
! 9807: /* Remember whether or not the value originally contained \r\n */
! 9808: if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
! 9809: x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
! 9810: }
! 9811: fclose(f);
! 9812: f = 0;
! 9813: if( x!=sz ){
! 9814: sqlite3_result_error(context, "edit() could not write the whole file", -1);
! 9815: goto edit_func_end;
! 9816: }
! 9817: zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
! 9818: if( zCmd==0 ){
! 9819: sqlite3_result_error_nomem(context);
! 9820: goto edit_func_end;
! 9821: }
! 9822: rc = system(zCmd);
! 9823: sqlite3_free(zCmd);
! 9824: if( rc ){
! 9825: sqlite3_result_error(context, "EDITOR returned non-zero", -1);
! 9826: goto edit_func_end;
! 9827: }
! 9828: f = fopen(zTempFile, "rb");
! 9829: if( f==0 ){
! 9830: sqlite3_result_error(context,
! 9831: "edit() cannot reopen temp file after edit", -1);
! 9832: goto edit_func_end;
! 9833: }
! 9834: fseek(f, 0, SEEK_END);
! 9835: sz = ftell(f);
! 9836: rewind(f);
! 9837: p = sqlite3_malloc64( sz+(bBin==0) );
! 9838: if( p==0 ){
! 9839: sqlite3_result_error_nomem(context);
! 9840: goto edit_func_end;
! 9841: }
! 9842: x = fread(p, 1, sz, f);
! 9843: fclose(f);
! 9844: f = 0;
! 9845: if( x!=sz ){
! 9846: sqlite3_result_error(context, "could not read back the whole file", -1);
! 9847: goto edit_func_end;
! 9848: }
! 9849: if( bBin ){
! 9850: sqlite3_result_blob64(context, p, sz, sqlite3_free);
! 9851: }else{
! 9852: sqlite3_int64 i, j;
! 9853: if( hasCRNL ){
! 9854: /* If the original contains \r\n then do no conversions back to \n */
! 9855: j = sz;
! 9856: }else{
! 9857: /* If the file did not originally contain \r\n then convert any new
! 9858: ** \r\n back into \n */
! 9859: for(i=j=0; i<sz; i++){
! 9860: if( p[i]=='\r' && p[i+1]=='\n' ) i++;
! 9861: p[j++] = p[i];
! 9862: }
! 9863: sz = j;
! 9864: p[sz] = 0;
! 9865: }
! 9866: sqlite3_result_text64(context, (const char*)p, sz,
! 9867: sqlite3_free, SQLITE_UTF8);
! 9868: }
! 9869: p = 0;
! 9870:
! 9871: edit_func_end:
! 9872: if( f ) fclose(f);
! 9873: unlink(zTempFile);
! 9874: sqlite3_free(zTempFile);
! 9875: sqlite3_free(p);
! 9876: }
! 9877: #endif /* SQLITE_NOHAVE_SYSTEM */
! 9878:
! 9879: /*
! 9880: ** Save or restore the current output mode
! 9881: */
! 9882: static void outputModePush(ShellState *p){
! 9883: p->modePrior = p->mode;
! 9884: memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
! 9885: memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
! 9886: }
! 9887: static void outputModePop(ShellState *p){
! 9888: p->mode = p->modePrior;
! 9889: memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
! 9890: memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
! 9891: }
! 9892:
! 9893: /*
! 9894: ** Output the given string as a hex-encoded blob (eg. X'1234' )
! 9895: */
! 9896: static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
! 9897: int i;
! 9898: char *zBlob = (char *)pBlob;
! 9899: raw_printf(out,"X'");
! 9900: for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
! 9901: raw_printf(out,"'");
! 9902: }
! 9903:
! 9904: /*
! 9905: ** Find a string that is not found anywhere in z[]. Return a pointer
! 9906: ** to that string.
! 9907: **
! 9908: ** Try to use zA and zB first. If both of those are already found in z[]
! 9909: ** then make up some string and store it in the buffer zBuf.
! 9910: */
! 9911: static const char *unused_string(
! 9912: const char *z, /* Result must not appear anywhere in z */
! 9913: const char *zA, const char *zB, /* Try these first */
! 9914: char *zBuf /* Space to store a generated string */
! 9915: ){
! 9916: unsigned i = 0;
! 9917: if( strstr(z, zA)==0 ) return zA;
! 9918: if( strstr(z, zB)==0 ) return zB;
! 9919: do{
! 9920: sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
! 9921: }while( strstr(z,zBuf)!=0 );
! 9922: return zBuf;
! 9923: }
! 9924:
! 9925: /*
! 9926: ** Output the given string as a quoted string using SQL quoting conventions.
! 9927: **
! 9928: ** See also: output_quoted_escaped_string()
! 9929: */
! 9930: static void output_quoted_string(FILE *out, const char *z){
! 9931: int i;
! 9932: char c;
! 9933: setBinaryMode(out, 1);
! 9934: for(i=0; (c = z[i])!=0 && c!='\''; i++){}
! 9935: if( c==0 ){
! 9936: utf8_printf(out,"'%s'",z);
! 9937: }else{
! 9938: raw_printf(out, "'");
! 9939: while( *z ){
! 9940: for(i=0; (c = z[i])!=0 && c!='\''; i++){}
! 9941: if( c=='\'' ) i++;
! 9942: if( i ){
! 9943: utf8_printf(out, "%.*s", i, z);
! 9944: z += i;
! 9945: }
! 9946: if( c=='\'' ){
! 9947: raw_printf(out, "'");
! 9948: continue;
! 9949: }
! 9950: if( c==0 ){
! 9951: break;
! 9952: }
! 9953: z++;
! 9954: }
! 9955: raw_printf(out, "'");
! 9956: }
! 9957: setTextMode(out, 1);
! 9958: }
! 9959:
! 9960: /*
! 9961: ** Output the given string as a quoted string using SQL quoting conventions.
! 9962: ** Additionallly , escape the "\n" and "\r" characters so that they do not
! 9963: ** get corrupted by end-of-line translation facilities in some operating
! 9964: ** systems.
! 9965: **
! 9966: ** This is like output_quoted_string() but with the addition of the \r\n
! 9967: ** escape mechanism.
! 9968: */
! 9969: static void output_quoted_escaped_string(FILE *out, const char *z){
! 9970: int i;
! 9971: char c;
! 9972: setBinaryMode(out, 1);
! 9973: for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
! 9974: if( c==0 ){
! 9975: utf8_printf(out,"'%s'",z);
! 9976: }else{
! 9977: const char *zNL = 0;
! 9978: const char *zCR = 0;
! 9979: int nNL = 0;
! 9980: int nCR = 0;
! 9981: char zBuf1[20], zBuf2[20];
! 9982: for(i=0; z[i]; i++){
! 9983: if( z[i]=='\n' ) nNL++;
! 9984: if( z[i]=='\r' ) nCR++;
! 9985: }
! 9986: if( nNL ){
! 9987: raw_printf(out, "replace(");
! 9988: zNL = unused_string(z, "\\n", "\\012", zBuf1);
! 9989: }
! 9990: if( nCR ){
! 9991: raw_printf(out, "replace(");
! 9992: zCR = unused_string(z, "\\r", "\\015", zBuf2);
! 9993: }
! 9994: raw_printf(out, "'");
! 9995: while( *z ){
! 9996: for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
! 9997: if( c=='\'' ) i++;
! 9998: if( i ){
! 9999: utf8_printf(out, "%.*s", i, z);
! 10000: z += i;
! 10001: }
! 10002: if( c=='\'' ){
! 10003: raw_printf(out, "'");
! 10004: continue;
! 10005: }
! 10006: if( c==0 ){
! 10007: break;
! 10008: }
! 10009: z++;
! 10010: if( c=='\n' ){
! 10011: raw_printf(out, "%s", zNL);
! 10012: continue;
! 10013: }
! 10014: raw_printf(out, "%s", zCR);
! 10015: }
! 10016: raw_printf(out, "'");
! 10017: if( nCR ){
! 10018: raw_printf(out, ",'%s',char(13))", zCR);
! 10019: }
! 10020: if( nNL ){
! 10021: raw_printf(out, ",'%s',char(10))", zNL);
! 10022: }
! 10023: }
! 10024: setTextMode(out, 1);
! 10025: }
! 10026:
! 10027: /*
! 10028: ** Output the given string as a quoted according to C or TCL quoting rules.
! 10029: */
! 10030: static void output_c_string(FILE *out, const char *z){
! 10031: unsigned int c;
! 10032: fputc('"', out);
! 10033: while( (c = *(z++))!=0 ){
! 10034: if( c=='\\' ){
! 10035: fputc(c, out);
! 10036: fputc(c, out);
! 10037: }else if( c=='"' ){
! 10038: fputc('\\', out);
! 10039: fputc('"', out);
! 10040: }else if( c=='\t' ){
! 10041: fputc('\\', out);
! 10042: fputc('t', out);
! 10043: }else if( c=='\n' ){
! 10044: fputc('\\', out);
! 10045: fputc('n', out);
! 10046: }else if( c=='\r' ){
! 10047: fputc('\\', out);
! 10048: fputc('r', out);
! 10049: }else if( !isprint(c&0xff) ){
! 10050: raw_printf(out, "\\%03o", c&0xff);
! 10051: }else{
! 10052: fputc(c, out);
! 10053: }
! 10054: }
! 10055: fputc('"', out);
! 10056: }
! 10057:
! 10058: /*
! 10059: ** Output the given string with characters that are special to
! 10060: ** HTML escaped.
! 10061: */
! 10062: static void output_html_string(FILE *out, const char *z){
! 10063: int i;
! 10064: if( z==0 ) z = "";
! 10065: while( *z ){
! 10066: for(i=0; z[i]
! 10067: && z[i]!='<'
! 10068: && z[i]!='&'
! 10069: && z[i]!='>'
! 10070: && z[i]!='\"'
! 10071: && z[i]!='\'';
! 10072: i++){}
! 10073: if( i>0 ){
! 10074: utf8_printf(out,"%.*s",i,z);
! 10075: }
! 10076: if( z[i]=='<' ){
! 10077: raw_printf(out,"<");
! 10078: }else if( z[i]=='&' ){
! 10079: raw_printf(out,"&");
! 10080: }else if( z[i]=='>' ){
! 10081: raw_printf(out,">");
! 10082: }else if( z[i]=='\"' ){
! 10083: raw_printf(out,""");
! 10084: }else if( z[i]=='\'' ){
! 10085: raw_printf(out,"'");
! 10086: }else{
! 10087: break;
! 10088: }
! 10089: z += i + 1;
! 10090: }
! 10091: }
! 10092:
! 10093: /*
! 10094: ** If a field contains any character identified by a 1 in the following
! 10095: ** array, then the string must be quoted for CSV.
! 10096: */
! 10097: static const char needCsvQuote[] = {
! 10098: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10099: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10100: 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
! 10101: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 10102: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 10103: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 10104: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 10105: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
! 10106: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10107: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10108: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10109: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10110: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10111: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10112: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10113: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
! 10114: };
! 10115:
! 10116: /*
! 10117: ** Output a single term of CSV. Actually, p->colSeparator is used for
! 10118: ** the separator, which may or may not be a comma. p->nullValue is
! 10119: ** the null value. Strings are quoted if necessary. The separator
! 10120: ** is only issued if bSep is true.
! 10121: */
! 10122: static void output_csv(ShellState *p, const char *z, int bSep){
! 10123: FILE *out = p->out;
! 10124: if( z==0 ){
! 10125: utf8_printf(out,"%s",p->nullValue);
! 10126: }else{
! 10127: int i;
! 10128: int nSep = strlen30(p->colSeparator);
! 10129: for(i=0; z[i]; i++){
! 10130: if( needCsvQuote[((unsigned char*)z)[i]]
! 10131: || (z[i]==p->colSeparator[0] &&
! 10132: (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
! 10133: i = 0;
! 10134: break;
! 10135: }
! 10136: }
! 10137: if( i==0 ){
! 10138: char *zQuoted = sqlite3_mprintf("\"%w\"", z);
! 10139: utf8_printf(out, "%s", zQuoted);
! 10140: sqlite3_free(zQuoted);
! 10141: }else{
! 10142: utf8_printf(out, "%s", z);
! 10143: }
! 10144: }
! 10145: if( bSep ){
! 10146: utf8_printf(p->out, "%s", p->colSeparator);
! 10147: }
! 10148: }
! 10149:
! 10150: /*
! 10151: ** This routine runs when the user presses Ctrl-C
! 10152: */
! 10153: static void interrupt_handler(int NotUsed){
! 10154: UNUSED_PARAMETER(NotUsed);
! 10155: seenInterrupt++;
! 10156: if( seenInterrupt>2 ) exit(1);
! 10157: if( globalDb ) sqlite3_interrupt(globalDb);
! 10158: }
! 10159:
! 10160: #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
! 10161: /*
! 10162: ** This routine runs for console events (e.g. Ctrl-C) on Win32
! 10163: */
! 10164: static BOOL WINAPI ConsoleCtrlHandler(
! 10165: DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
! 10166: ){
! 10167: if( dwCtrlType==CTRL_C_EVENT ){
! 10168: interrupt_handler(0);
! 10169: return TRUE;
! 10170: }
! 10171: return FALSE;
! 10172: }
! 10173: #endif
! 10174:
! 10175: #ifndef SQLITE_OMIT_AUTHORIZATION
! 10176: /*
! 10177: ** When the ".auth ON" is set, the following authorizer callback is
! 10178: ** invoked. It always returns SQLITE_OK.
! 10179: */
! 10180: static int shellAuth(
! 10181: void *pClientData,
! 10182: int op,
! 10183: const char *zA1,
! 10184: const char *zA2,
! 10185: const char *zA3,
! 10186: const char *zA4
! 10187: ){
! 10188: ShellState *p = (ShellState*)pClientData;
! 10189: static const char *azAction[] = { 0,
! 10190: "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
! 10191: "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
! 10192: "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
! 10193: "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
! 10194: "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
! 10195: "DROP_TRIGGER", "DROP_VIEW", "INSERT",
! 10196: "PRAGMA", "READ", "SELECT",
! 10197: "TRANSACTION", "UPDATE", "ATTACH",
! 10198: "DETACH", "ALTER_TABLE", "REINDEX",
! 10199: "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
! 10200: "FUNCTION", "SAVEPOINT", "RECURSIVE"
! 10201: };
! 10202: int i;
! 10203: const char *az[4];
! 10204: az[0] = zA1;
! 10205: az[1] = zA2;
! 10206: az[2] = zA3;
! 10207: az[3] = zA4;
! 10208: utf8_printf(p->out, "authorizer: %s", azAction[op]);
! 10209: for(i=0; i<4; i++){
! 10210: raw_printf(p->out, " ");
! 10211: if( az[i] ){
! 10212: output_c_string(p->out, az[i]);
! 10213: }else{
! 10214: raw_printf(p->out, "NULL");
! 10215: }
! 10216: }
! 10217: raw_printf(p->out, "\n");
! 10218: return SQLITE_OK;
! 10219: }
! 10220: #endif
! 10221:
! 10222: /*
! 10223: ** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
! 10224: **
! 10225: ** This routine converts some CREATE TABLE statements for shadow tables
! 10226: ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
! 10227: */
! 10228: static void printSchemaLine(FILE *out, const char *z, const char *zTail){
! 10229: if( z==0 ) return;
! 10230: if( zTail==0 ) return;
! 10231: if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
! 10232: utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
! 10233: }else{
! 10234: utf8_printf(out, "%s%s", z, zTail);
! 10235: }
! 10236: }
! 10237: static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
! 10238: char c = z[n];
! 10239: z[n] = 0;
! 10240: printSchemaLine(out, z, zTail);
! 10241: z[n] = c;
! 10242: }
! 10243:
! 10244: /*
! 10245: ** Return true if string z[] has nothing but whitespace and comments to the
! 10246: ** end of the first line.
! 10247: */
! 10248: static int wsToEol(const char *z){
! 10249: int i;
! 10250: for(i=0; z[i]; i++){
! 10251: if( z[i]=='\n' ) return 1;
! 10252: if( IsSpace(z[i]) ) continue;
! 10253: if( z[i]=='-' && z[i+1]=='-' ) return 1;
! 10254: return 0;
! 10255: }
! 10256: return 1;
! 10257: }
! 10258:
! 10259: /*
! 10260: ** Add a new entry to the EXPLAIN QUERY PLAN data
! 10261: */
! 10262: static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
! 10263: EQPGraphRow *pNew;
! 10264: int nText = strlen30(zText);
! 10265: if( p->autoEQPtest ){
! 10266: utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
! 10267: }
! 10268: pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
! 10269: if( pNew==0 ) shell_out_of_memory();
! 10270: pNew->iEqpId = iEqpId;
! 10271: pNew->iParentId = p2;
! 10272: memcpy(pNew->zText, zText, nText+1);
! 10273: pNew->pNext = 0;
! 10274: if( p->sGraph.pLast ){
! 10275: p->sGraph.pLast->pNext = pNew;
! 10276: }else{
! 10277: p->sGraph.pRow = pNew;
! 10278: }
! 10279: p->sGraph.pLast = pNew;
! 10280: }
! 10281:
! 10282: /*
! 10283: ** Free and reset the EXPLAIN QUERY PLAN data that has been collected
! 10284: ** in p->sGraph.
! 10285: */
! 10286: static void eqp_reset(ShellState *p){
! 10287: EQPGraphRow *pRow, *pNext;
! 10288: for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
! 10289: pNext = pRow->pNext;
! 10290: sqlite3_free(pRow);
! 10291: }
! 10292: memset(&p->sGraph, 0, sizeof(p->sGraph));
! 10293: }
! 10294:
! 10295: /* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
! 10296: ** pOld, or return the first such line if pOld is NULL
! 10297: */
! 10298: static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
! 10299: EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
! 10300: while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
! 10301: return pRow;
! 10302: }
! 10303:
! 10304: /* Render a single level of the graph that has iEqpId as its parent. Called
! 10305: ** recursively to render sublevels.
! 10306: */
! 10307: static void eqp_render_level(ShellState *p, int iEqpId){
! 10308: EQPGraphRow *pRow, *pNext;
! 10309: int n = strlen30(p->sGraph.zPrefix);
! 10310: char *z;
! 10311: for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
! 10312: pNext = eqp_next_row(p, iEqpId, pRow);
! 10313: z = pRow->zText;
! 10314: utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
! 10315: if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
! 10316: memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
! 10317: eqp_render_level(p, pRow->iEqpId);
! 10318: p->sGraph.zPrefix[n] = 0;
! 10319: }
! 10320: }
! 10321: }
! 10322:
! 10323: /*
! 10324: ** Display and reset the EXPLAIN QUERY PLAN data
! 10325: */
! 10326: static void eqp_render(ShellState *p){
! 10327: EQPGraphRow *pRow = p->sGraph.pRow;
! 10328: if( pRow ){
! 10329: if( pRow->zText[0]=='-' ){
! 10330: if( pRow->pNext==0 ){
! 10331: eqp_reset(p);
! 10332: return;
! 10333: }
! 10334: utf8_printf(p->out, "%s\n", pRow->zText+3);
! 10335: p->sGraph.pRow = pRow->pNext;
! 10336: sqlite3_free(pRow);
! 10337: }else{
! 10338: utf8_printf(p->out, "QUERY PLAN\n");
! 10339: }
! 10340: p->sGraph.zPrefix[0] = 0;
! 10341: eqp_render_level(p, 0);
! 10342: eqp_reset(p);
! 10343: }
! 10344: }
! 10345:
! 10346: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
! 10347: /*
! 10348: ** Progress handler callback.
! 10349: */
! 10350: static int progress_handler(void *pClientData) {
! 10351: ShellState *p = (ShellState*)pClientData;
! 10352: p->nProgress++;
! 10353: if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
! 10354: raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
! 10355: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
! 10356: if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
! 10357: return 1;
! 10358: }
! 10359: if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
! 10360: raw_printf(p->out, "Progress %u\n", p->nProgress);
! 10361: }
! 10362: return 0;
! 10363: }
! 10364: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
! 10365:
! 10366: /*
! 10367: ** This is the callback routine that the shell
! 10368: ** invokes for each row of a query result.
! 10369: */
! 10370: static int shell_callback(
! 10371: void *pArg,
! 10372: int nArg, /* Number of result columns */
! 10373: char **azArg, /* Text of each result column */
! 10374: char **azCol, /* Column names */
! 10375: int *aiType /* Column types */
! 10376: ){
! 10377: int i;
! 10378: ShellState *p = (ShellState*)pArg;
! 10379:
! 10380: if( azArg==0 ) return 0;
! 10381: switch( p->cMode ){
! 10382: case MODE_Line: {
! 10383: int w = 5;
! 10384: if( azArg==0 ) break;
! 10385: for(i=0; i<nArg; i++){
! 10386: int len = strlen30(azCol[i] ? azCol[i] : "");
! 10387: if( len>w ) w = len;
! 10388: }
! 10389: if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
! 10390: for(i=0; i<nArg; i++){
! 10391: utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
! 10392: azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
! 10393: }
! 10394: break;
! 10395: }
! 10396: case MODE_Explain:
! 10397: case MODE_Column: {
! 10398: static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
! 10399: const int *colWidth;
! 10400: int showHdr;
! 10401: char *rowSep;
! 10402: if( p->cMode==MODE_Column ){
! 10403: colWidth = p->colWidth;
! 10404: showHdr = p->showHeader;
! 10405: rowSep = p->rowSeparator;
! 10406: }else{
! 10407: colWidth = aExplainWidths;
! 10408: showHdr = 1;
! 10409: rowSep = SEP_Row;
! 10410: }
! 10411: if( p->cnt++==0 ){
! 10412: for(i=0; i<nArg; i++){
! 10413: int w, n;
! 10414: if( i<ArraySize(p->colWidth) ){
! 10415: w = colWidth[i];
! 10416: }else{
! 10417: w = 0;
! 10418: }
! 10419: if( w==0 ){
! 10420: w = strlenChar(azCol[i] ? azCol[i] : "");
! 10421: if( w<10 ) w = 10;
! 10422: n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
! 10423: if( w<n ) w = n;
! 10424: }
! 10425: if( i<ArraySize(p->actualWidth) ){
! 10426: p->actualWidth[i] = w;
! 10427: }
! 10428: if( showHdr ){
! 10429: utf8_width_print(p->out, w, azCol[i]);
! 10430: utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
! 10431: }
! 10432: }
! 10433: if( showHdr ){
! 10434: for(i=0; i<nArg; i++){
! 10435: int w;
! 10436: if( i<ArraySize(p->actualWidth) ){
! 10437: w = p->actualWidth[i];
! 10438: if( w<0 ) w = -w;
! 10439: }else{
! 10440: w = 10;
! 10441: }
! 10442: utf8_printf(p->out,"%-*.*s%s",w,w,
! 10443: "----------------------------------------------------------"
! 10444: "----------------------------------------------------------",
! 10445: i==nArg-1 ? rowSep : " ");
! 10446: }
! 10447: }
! 10448: }
! 10449: if( azArg==0 ) break;
! 10450: for(i=0; i<nArg; i++){
! 10451: int w;
! 10452: if( i<ArraySize(p->actualWidth) ){
! 10453: w = p->actualWidth[i];
! 10454: }else{
! 10455: w = 10;
! 10456: }
! 10457: if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
! 10458: w = strlenChar(azArg[i]);
! 10459: }
! 10460: if( i==1 && p->aiIndent && p->pStmt ){
! 10461: if( p->iIndent<p->nIndent ){
! 10462: utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
! 10463: }
! 10464: p->iIndent++;
! 10465: }
! 10466: utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
! 10467: utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
! 10468: }
! 10469: break;
! 10470: }
! 10471: case MODE_Semi: { /* .schema and .fullschema output */
! 10472: printSchemaLine(p->out, azArg[0], ";\n");
! 10473: break;
! 10474: }
! 10475: case MODE_Pretty: { /* .schema and .fullschema with --indent */
! 10476: char *z;
! 10477: int j;
! 10478: int nParen = 0;
! 10479: char cEnd = 0;
! 10480: char c;
! 10481: int nLine = 0;
! 10482: assert( nArg==1 );
! 10483: if( azArg[0]==0 ) break;
! 10484: if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
! 10485: || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
! 10486: ){
! 10487: utf8_printf(p->out, "%s;\n", azArg[0]);
! 10488: break;
! 10489: }
! 10490: z = sqlite3_mprintf("%s", azArg[0]);
! 10491: j = 0;
1.4 misho 10492: for(i=0; IsSpace(z[i]); i++){}
10493: for(; (c = z[i])!=0; i++){
10494: if( IsSpace(c) ){
1.4.2.2 ! misho 10495: if( z[j-1]=='\r' ) z[j-1] = '\n';
1.4 misho 10496: if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
10497: }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
10498: j--;
10499: }
1.4.2.2 ! misho 10500: z[j++] = c;
! 10501: }
! 10502: while( j>0 && IsSpace(z[j-1]) ){ j--; }
! 10503: z[j] = 0;
! 10504: if( strlen30(z)>=79 ){
! 10505: for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */
! 10506: if( c==cEnd ){
! 10507: cEnd = 0;
! 10508: }else if( c=='"' || c=='\'' || c=='`' ){
! 10509: cEnd = c;
! 10510: }else if( c=='[' ){
! 10511: cEnd = ']';
! 10512: }else if( c=='-' && z[i+1]=='-' ){
! 10513: cEnd = '\n';
! 10514: }else if( c=='(' ){
! 10515: nParen++;
! 10516: }else if( c==')' ){
! 10517: nParen--;
! 10518: if( nLine>0 && nParen==0 && j>0 ){
! 10519: printSchemaLineN(p->out, z, j, "\n");
! 10520: j = 0;
! 10521: }
! 10522: }
! 10523: z[j++] = c;
! 10524: if( nParen==1 && cEnd==0
! 10525: && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
! 10526: ){
! 10527: if( c=='\n' ) j--;
! 10528: printSchemaLineN(p->out, z, j, "\n ");
! 10529: j = 0;
! 10530: nLine++;
! 10531: while( IsSpace(z[i+1]) ){ i++; }
! 10532: }
! 10533: }
! 10534: z[j] = 0;
! 10535: }
! 10536: printSchemaLine(p->out, z, ";\n");
! 10537: sqlite3_free(z);
! 10538: break;
! 10539: }
! 10540: case MODE_List: {
! 10541: if( p->cnt++==0 && p->showHeader ){
! 10542: for(i=0; i<nArg; i++){
! 10543: utf8_printf(p->out,"%s%s",azCol[i],
! 10544: i==nArg-1 ? p->rowSeparator : p->colSeparator);
! 10545: }
! 10546: }
! 10547: if( azArg==0 ) break;
! 10548: for(i=0; i<nArg; i++){
! 10549: char *z = azArg[i];
! 10550: if( z==0 ) z = p->nullValue;
! 10551: utf8_printf(p->out, "%s", z);
! 10552: if( i<nArg-1 ){
! 10553: utf8_printf(p->out, "%s", p->colSeparator);
! 10554: }else{
! 10555: utf8_printf(p->out, "%s", p->rowSeparator);
! 10556: }
! 10557: }
! 10558: break;
! 10559: }
! 10560: case MODE_Html: {
! 10561: if( p->cnt++==0 && p->showHeader ){
! 10562: raw_printf(p->out,"<TR>");
! 10563: for(i=0; i<nArg; i++){
! 10564: raw_printf(p->out,"<TH>");
! 10565: output_html_string(p->out, azCol[i]);
! 10566: raw_printf(p->out,"</TH>\n");
! 10567: }
! 10568: raw_printf(p->out,"</TR>\n");
! 10569: }
! 10570: if( azArg==0 ) break;
! 10571: raw_printf(p->out,"<TR>");
! 10572: for(i=0; i<nArg; i++){
! 10573: raw_printf(p->out,"<TD>");
! 10574: output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
! 10575: raw_printf(p->out,"</TD>\n");
! 10576: }
! 10577: raw_printf(p->out,"</TR>\n");
! 10578: break;
! 10579: }
! 10580: case MODE_Tcl: {
! 10581: if( p->cnt++==0 && p->showHeader ){
! 10582: for(i=0; i<nArg; i++){
! 10583: output_c_string(p->out,azCol[i] ? azCol[i] : "");
! 10584: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
! 10585: }
! 10586: utf8_printf(p->out, "%s", p->rowSeparator);
! 10587: }
! 10588: if( azArg==0 ) break;
! 10589: for(i=0; i<nArg; i++){
! 10590: output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
! 10591: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
! 10592: }
! 10593: utf8_printf(p->out, "%s", p->rowSeparator);
! 10594: break;
! 10595: }
! 10596: case MODE_Csv: {
! 10597: setBinaryMode(p->out, 1);
! 10598: if( p->cnt++==0 && p->showHeader ){
! 10599: for(i=0; i<nArg; i++){
! 10600: output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
! 10601: }
! 10602: utf8_printf(p->out, "%s", p->rowSeparator);
! 10603: }
! 10604: if( nArg>0 ){
! 10605: for(i=0; i<nArg; i++){
! 10606: output_csv(p, azArg[i], i<nArg-1);
! 10607: }
! 10608: utf8_printf(p->out, "%s", p->rowSeparator);
! 10609: }
! 10610: setTextMode(p->out, 1);
! 10611: break;
! 10612: }
! 10613: case MODE_Insert: {
! 10614: if( azArg==0 ) break;
! 10615: utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
! 10616: if( p->showHeader ){
! 10617: raw_printf(p->out,"(");
! 10618: for(i=0; i<nArg; i++){
! 10619: if( i>0 ) raw_printf(p->out, ",");
! 10620: if( quoteChar(azCol[i]) ){
! 10621: char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
! 10622: utf8_printf(p->out, "%s", z);
! 10623: sqlite3_free(z);
! 10624: }else{
! 10625: raw_printf(p->out, "%s", azCol[i]);
! 10626: }
! 10627: }
! 10628: raw_printf(p->out,")");
! 10629: }
! 10630: p->cnt++;
! 10631: for(i=0; i<nArg; i++){
! 10632: raw_printf(p->out, i>0 ? "," : " VALUES(");
! 10633: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
! 10634: utf8_printf(p->out,"NULL");
! 10635: }else if( aiType && aiType[i]==SQLITE_TEXT ){
! 10636: if( ShellHasFlag(p, SHFLG_Newlines) ){
! 10637: output_quoted_string(p->out, azArg[i]);
! 10638: }else{
! 10639: output_quoted_escaped_string(p->out, azArg[i]);
! 10640: }
! 10641: }else if( aiType && aiType[i]==SQLITE_INTEGER ){
! 10642: utf8_printf(p->out,"%s", azArg[i]);
! 10643: }else if( aiType && aiType[i]==SQLITE_FLOAT ){
! 10644: char z[50];
! 10645: double r = sqlite3_column_double(p->pStmt, i);
! 10646: sqlite3_uint64 ur;
! 10647: memcpy(&ur,&r,sizeof(r));
! 10648: if( ur==0x7ff0000000000000LL ){
! 10649: raw_printf(p->out, "1e999");
! 10650: }else if( ur==0xfff0000000000000LL ){
! 10651: raw_printf(p->out, "-1e999");
! 10652: }else{
! 10653: sqlite3_snprintf(50,z,"%!.20g", r);
! 10654: raw_printf(p->out, "%s", z);
! 10655: }
! 10656: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
! 10657: const void *pBlob = sqlite3_column_blob(p->pStmt, i);
! 10658: int nBlob = sqlite3_column_bytes(p->pStmt, i);
! 10659: output_hex_blob(p->out, pBlob, nBlob);
! 10660: }else if( isNumber(azArg[i], 0) ){
! 10661: utf8_printf(p->out,"%s", azArg[i]);
! 10662: }else if( ShellHasFlag(p, SHFLG_Newlines) ){
! 10663: output_quoted_string(p->out, azArg[i]);
! 10664: }else{
! 10665: output_quoted_escaped_string(p->out, azArg[i]);
! 10666: }
! 10667: }
! 10668: raw_printf(p->out,");\n");
! 10669: break;
! 10670: }
! 10671: case MODE_Quote: {
! 10672: if( azArg==0 ) break;
! 10673: if( p->cnt==0 && p->showHeader ){
! 10674: for(i=0; i<nArg; i++){
! 10675: if( i>0 ) raw_printf(p->out, ",");
! 10676: output_quoted_string(p->out, azCol[i]);
! 10677: }
! 10678: raw_printf(p->out,"\n");
! 10679: }
! 10680: p->cnt++;
! 10681: for(i=0; i<nArg; i++){
! 10682: if( i>0 ) raw_printf(p->out, ",");
! 10683: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
! 10684: utf8_printf(p->out,"NULL");
! 10685: }else if( aiType && aiType[i]==SQLITE_TEXT ){
! 10686: output_quoted_string(p->out, azArg[i]);
! 10687: }else if( aiType && aiType[i]==SQLITE_INTEGER ){
! 10688: utf8_printf(p->out,"%s", azArg[i]);
! 10689: }else if( aiType && aiType[i]==SQLITE_FLOAT ){
! 10690: char z[50];
! 10691: double r = sqlite3_column_double(p->pStmt, i);
! 10692: sqlite3_snprintf(50,z,"%!.20g", r);
! 10693: raw_printf(p->out, "%s", z);
! 10694: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
! 10695: const void *pBlob = sqlite3_column_blob(p->pStmt, i);
! 10696: int nBlob = sqlite3_column_bytes(p->pStmt, i);
! 10697: output_hex_blob(p->out, pBlob, nBlob);
! 10698: }else if( isNumber(azArg[i], 0) ){
! 10699: utf8_printf(p->out,"%s", azArg[i]);
! 10700: }else{
! 10701: output_quoted_string(p->out, azArg[i]);
! 10702: }
! 10703: }
! 10704: raw_printf(p->out,"\n");
! 10705: break;
! 10706: }
! 10707: case MODE_Ascii: {
! 10708: if( p->cnt++==0 && p->showHeader ){
! 10709: for(i=0; i<nArg; i++){
! 10710: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
! 10711: utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
! 10712: }
! 10713: utf8_printf(p->out, "%s", p->rowSeparator);
! 10714: }
! 10715: if( azArg==0 ) break;
! 10716: for(i=0; i<nArg; i++){
! 10717: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
! 10718: utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
! 10719: }
! 10720: utf8_printf(p->out, "%s", p->rowSeparator);
! 10721: break;
! 10722: }
! 10723: case MODE_EQP: {
! 10724: eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
! 10725: break;
! 10726: }
! 10727: }
! 10728: return 0;
! 10729: }
! 10730:
! 10731: /*
! 10732: ** This is the callback routine that the SQLite library
! 10733: ** invokes for each row of a query result.
! 10734: */
! 10735: static int callback(void *pArg, int nArg, char **azArg, char **azCol){
! 10736: /* since we don't have type info, call the shell_callback with a NULL value */
! 10737: return shell_callback(pArg, nArg, azArg, azCol, NULL);
! 10738: }
! 10739:
! 10740: /*
! 10741: ** This is the callback routine from sqlite3_exec() that appends all
! 10742: ** output onto the end of a ShellText object.
! 10743: */
! 10744: static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
! 10745: ShellText *p = (ShellText*)pArg;
! 10746: int i;
! 10747: UNUSED_PARAMETER(az);
! 10748: if( azArg==0 ) return 0;
! 10749: if( p->n ) appendText(p, "|", 0);
! 10750: for(i=0; i<nArg; i++){
! 10751: if( i ) appendText(p, ",", 0);
! 10752: if( azArg[i] ) appendText(p, azArg[i], 0);
! 10753: }
! 10754: return 0;
! 10755: }
! 10756:
! 10757: /*
! 10758: ** Generate an appropriate SELFTEST table in the main database.
! 10759: */
! 10760: static void createSelftestTable(ShellState *p){
! 10761: char *zErrMsg = 0;
! 10762: sqlite3_exec(p->db,
! 10763: "SAVEPOINT selftest_init;\n"
! 10764: "CREATE TABLE IF NOT EXISTS selftest(\n"
! 10765: " tno INTEGER PRIMARY KEY,\n" /* Test number */
! 10766: " op TEXT,\n" /* Operator: memo run */
! 10767: " cmd TEXT,\n" /* Command text */
! 10768: " ans TEXT\n" /* Desired answer */
! 10769: ");"
! 10770: "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
! 10771: "INSERT INTO [_shell$self](rowid,op,cmd)\n"
! 10772: " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
! 10773: " 'memo','Tests generated by --init');\n"
! 10774: "INSERT INTO [_shell$self]\n"
! 10775: " SELECT 'run',\n"
! 10776: " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
! 10777: "FROM sqlite_master ORDER BY 2'',224))',\n"
! 10778: " hex(sha3_query('SELECT type,name,tbl_name,sql "
! 10779: "FROM sqlite_master ORDER BY 2',224));\n"
! 10780: "INSERT INTO [_shell$self]\n"
! 10781: " SELECT 'run',"
! 10782: " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
! 10783: " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
! 10784: " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
! 10785: " FROM (\n"
! 10786: " SELECT name FROM sqlite_master\n"
! 10787: " WHERE type='table'\n"
! 10788: " AND name<>'selftest'\n"
! 10789: " AND coalesce(rootpage,0)>0\n"
! 10790: " )\n"
! 10791: " ORDER BY name;\n"
! 10792: "INSERT INTO [_shell$self]\n"
! 10793: " VALUES('run','PRAGMA integrity_check','ok');\n"
! 10794: "INSERT INTO selftest(tno,op,cmd,ans)"
! 10795: " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
! 10796: "DROP TABLE [_shell$self];"
! 10797: ,0,0,&zErrMsg);
! 10798: if( zErrMsg ){
! 10799: utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
! 10800: sqlite3_free(zErrMsg);
! 10801: }
! 10802: sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
! 10803: }
! 10804:
! 10805:
! 10806: /*
! 10807: ** Set the destination table field of the ShellState structure to
! 10808: ** the name of the table given. Escape any quote characters in the
! 10809: ** table name.
! 10810: */
! 10811: static void set_table_name(ShellState *p, const char *zName){
! 10812: int i, n;
! 10813: char cQuote;
! 10814: char *z;
! 10815:
! 10816: if( p->zDestTable ){
! 10817: free(p->zDestTable);
! 10818: p->zDestTable = 0;
! 10819: }
! 10820: if( zName==0 ) return;
! 10821: cQuote = quoteChar(zName);
! 10822: n = strlen30(zName);
! 10823: if( cQuote ) n += n+2;
! 10824: z = p->zDestTable = malloc( n+1 );
! 10825: if( z==0 ) shell_out_of_memory();
! 10826: n = 0;
! 10827: if( cQuote ) z[n++] = cQuote;
! 10828: for(i=0; zName[i]; i++){
! 10829: z[n++] = zName[i];
! 10830: if( zName[i]==cQuote ) z[n++] = cQuote;
! 10831: }
! 10832: if( cQuote ) z[n++] = cQuote;
! 10833: z[n] = 0;
! 10834: }
! 10835:
! 10836:
! 10837: /*
! 10838: ** Execute a query statement that will generate SQL output. Print
! 10839: ** the result columns, comma-separated, on a line and then add a
! 10840: ** semicolon terminator to the end of that line.
! 10841: **
! 10842: ** If the number of columns is 1 and that column contains text "--"
! 10843: ** then write the semicolon on a separate line. That way, if a
! 10844: ** "--" comment occurs at the end of the statement, the comment
! 10845: ** won't consume the semicolon terminator.
! 10846: */
! 10847: static int run_table_dump_query(
! 10848: ShellState *p, /* Query context */
! 10849: const char *zSelect, /* SELECT statement to extract content */
! 10850: const char *zFirstRow /* Print before first row, if not NULL */
! 10851: ){
! 10852: sqlite3_stmt *pSelect;
! 10853: int rc;
! 10854: int nResult;
! 10855: int i;
! 10856: const char *z;
! 10857: rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
! 10858: if( rc!=SQLITE_OK || !pSelect ){
! 10859: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
! 10860: sqlite3_errmsg(p->db));
! 10861: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
! 10862: return rc;
! 10863: }
! 10864: rc = sqlite3_step(pSelect);
! 10865: nResult = sqlite3_column_count(pSelect);
! 10866: while( rc==SQLITE_ROW ){
! 10867: if( zFirstRow ){
! 10868: utf8_printf(p->out, "%s", zFirstRow);
! 10869: zFirstRow = 0;
! 10870: }
! 10871: z = (const char*)sqlite3_column_text(pSelect, 0);
! 10872: utf8_printf(p->out, "%s", z);
! 10873: for(i=1; i<nResult; i++){
! 10874: utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
! 10875: }
! 10876: if( z==0 ) z = "";
! 10877: while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
! 10878: if( z[0] ){
! 10879: raw_printf(p->out, "\n;\n");
! 10880: }else{
! 10881: raw_printf(p->out, ";\n");
! 10882: }
! 10883: rc = sqlite3_step(pSelect);
! 10884: }
! 10885: rc = sqlite3_finalize(pSelect);
! 10886: if( rc!=SQLITE_OK ){
! 10887: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
! 10888: sqlite3_errmsg(p->db));
! 10889: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
! 10890: }
! 10891: return rc;
! 10892: }
! 10893:
! 10894: /*
! 10895: ** Allocate space and save off current error string.
! 10896: */
! 10897: static char *save_err_msg(
! 10898: sqlite3 *db /* Database to query */
! 10899: ){
! 10900: int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
! 10901: char *zErrMsg = sqlite3_malloc64(nErrMsg);
! 10902: if( zErrMsg ){
! 10903: memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
! 10904: }
! 10905: return zErrMsg;
! 10906: }
! 10907:
! 10908: #ifdef __linux__
! 10909: /*
! 10910: ** Attempt to display I/O stats on Linux using /proc/PID/io
! 10911: */
! 10912: static void displayLinuxIoStats(FILE *out){
! 10913: FILE *in;
! 10914: char z[200];
! 10915: sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
! 10916: in = fopen(z, "rb");
! 10917: if( in==0 ) return;
! 10918: while( fgets(z, sizeof(z), in)!=0 ){
! 10919: static const struct {
! 10920: const char *zPattern;
! 10921: const char *zDesc;
! 10922: } aTrans[] = {
! 10923: { "rchar: ", "Bytes received by read():" },
! 10924: { "wchar: ", "Bytes sent to write():" },
! 10925: { "syscr: ", "Read() system calls:" },
! 10926: { "syscw: ", "Write() system calls:" },
! 10927: { "read_bytes: ", "Bytes read from storage:" },
! 10928: { "write_bytes: ", "Bytes written to storage:" },
! 10929: { "cancelled_write_bytes: ", "Cancelled write bytes:" },
! 10930: };
! 10931: int i;
! 10932: for(i=0; i<ArraySize(aTrans); i++){
! 10933: int n = strlen30(aTrans[i].zPattern);
! 10934: if( strncmp(aTrans[i].zPattern, z, n)==0 ){
! 10935: utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
! 10936: break;
! 10937: }
! 10938: }
! 10939: }
! 10940: fclose(in);
! 10941: }
! 10942: #endif
! 10943:
! 10944: /*
! 10945: ** Display a single line of status using 64-bit values.
! 10946: */
! 10947: static void displayStatLine(
! 10948: ShellState *p, /* The shell context */
! 10949: char *zLabel, /* Label for this one line */
! 10950: char *zFormat, /* Format for the result */
! 10951: int iStatusCtrl, /* Which status to display */
! 10952: int bReset /* True to reset the stats */
! 10953: ){
! 10954: sqlite3_int64 iCur = -1;
! 10955: sqlite3_int64 iHiwtr = -1;
! 10956: int i, nPercent;
! 10957: char zLine[200];
! 10958: sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
! 10959: for(i=0, nPercent=0; zFormat[i]; i++){
! 10960: if( zFormat[i]=='%' ) nPercent++;
! 10961: }
! 10962: if( nPercent>1 ){
! 10963: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
! 10964: }else{
! 10965: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
! 10966: }
! 10967: raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
! 10968: }
! 10969:
! 10970: /*
! 10971: ** Display memory stats.
! 10972: */
! 10973: static int display_stats(
! 10974: sqlite3 *db, /* Database to query */
! 10975: ShellState *pArg, /* Pointer to ShellState */
! 10976: int bReset /* True to reset the stats */
! 10977: ){
! 10978: int iCur;
! 10979: int iHiwtr;
! 10980: FILE *out;
! 10981: if( pArg==0 || pArg->out==0 ) return 0;
! 10982: out = pArg->out;
! 10983:
! 10984: if( pArg->pStmt && (pArg->statsOn & 2) ){
! 10985: int nCol, i, x;
! 10986: sqlite3_stmt *pStmt = pArg->pStmt;
! 10987: char z[100];
! 10988: nCol = sqlite3_column_count(pStmt);
! 10989: raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
! 10990: for(i=0; i<nCol; i++){
! 10991: sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
! 10992: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
! 10993: #ifndef SQLITE_OMIT_DECLTYPE
! 10994: sqlite3_snprintf(30, z+x, "declared type:");
! 10995: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
! 10996: #endif
! 10997: #ifdef SQLITE_ENABLE_COLUMN_METADATA
! 10998: sqlite3_snprintf(30, z+x, "database name:");
! 10999: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
! 11000: sqlite3_snprintf(30, z+x, "table name:");
! 11001: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
! 11002: sqlite3_snprintf(30, z+x, "origin name:");
! 11003: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
! 11004: #endif
! 11005: }
! 11006: }
! 11007:
! 11008: displayStatLine(pArg, "Memory Used:",
! 11009: "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
! 11010: displayStatLine(pArg, "Number of Outstanding Allocations:",
! 11011: "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
! 11012: if( pArg->shellFlgs & SHFLG_Pagecache ){
! 11013: displayStatLine(pArg, "Number of Pcache Pages Used:",
! 11014: "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
! 11015: }
! 11016: displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
! 11017: "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
! 11018: displayStatLine(pArg, "Largest Allocation:",
! 11019: "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
! 11020: displayStatLine(pArg, "Largest Pcache Allocation:",
! 11021: "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
! 11022: #ifdef YYTRACKMAXSTACKDEPTH
! 11023: displayStatLine(pArg, "Deepest Parser Stack:",
! 11024: "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
! 11025: #endif
! 11026:
! 11027: if( db ){
! 11028: if( pArg->shellFlgs & SHFLG_Lookaside ){
! 11029: iHiwtr = iCur = -1;
! 11030: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
! 11031: &iCur, &iHiwtr, bReset);
! 11032: raw_printf(pArg->out,
! 11033: "Lookaside Slots Used: %d (max %d)\n",
! 11034: iCur, iHiwtr);
! 11035: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
! 11036: &iCur, &iHiwtr, bReset);
! 11037: raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
! 11038: iHiwtr);
! 11039: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
! 11040: &iCur, &iHiwtr, bReset);
! 11041: raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
! 11042: iHiwtr);
! 11043: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
! 11044: &iCur, &iHiwtr, bReset);
! 11045: raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
! 11046: iHiwtr);
! 11047: }
! 11048: iHiwtr = iCur = -1;
! 11049: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
! 11050: raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
! 11051: iCur);
! 11052: iHiwtr = iCur = -1;
! 11053: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
! 11054: raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
! 11055: iHiwtr = iCur = -1;
! 11056: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
! 11057: raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
! 11058: iHiwtr = iCur = -1;
! 11059: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
! 11060: raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
! 11061: iHiwtr = iCur = -1;
! 11062: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
! 11063: raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
! 11064: iHiwtr = iCur = -1;
! 11065: sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
! 11066: raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
! 11067: iCur);
! 11068: iHiwtr = iCur = -1;
! 11069: sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
! 11070: raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
! 11071: iCur);
! 11072: }
! 11073:
! 11074: if( pArg->pStmt ){
! 11075: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
! 11076: bReset);
! 11077: raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
! 11078: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
! 11079: raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
! 11080: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
! 11081: raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
! 11082: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
! 11083: raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
! 11084: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
! 11085: raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
! 11086: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
! 11087: raw_printf(pArg->out, "Number of times run: %d\n", iCur);
! 11088: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
! 11089: raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
! 11090: }
! 11091:
! 11092: #ifdef __linux__
! 11093: displayLinuxIoStats(pArg->out);
! 11094: #endif
! 11095:
! 11096: /* Do not remove this machine readable comment: extra-stats-output-here */
! 11097:
! 11098: return 0;
! 11099: }
! 11100:
! 11101: /*
! 11102: ** Display scan stats.
! 11103: */
! 11104: static void display_scanstats(
! 11105: sqlite3 *db, /* Database to query */
! 11106: ShellState *pArg /* Pointer to ShellState */
! 11107: ){
! 11108: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
! 11109: UNUSED_PARAMETER(db);
! 11110: UNUSED_PARAMETER(pArg);
! 11111: #else
! 11112: int i, k, n, mx;
! 11113: raw_printf(pArg->out, "-------- scanstats --------\n");
! 11114: mx = 0;
! 11115: for(k=0; k<=mx; k++){
! 11116: double rEstLoop = 1.0;
! 11117: for(i=n=0; 1; i++){
! 11118: sqlite3_stmt *p = pArg->pStmt;
! 11119: sqlite3_int64 nLoop, nVisit;
! 11120: double rEst;
! 11121: int iSid;
! 11122: const char *zExplain;
! 11123: if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
! 11124: break;
! 11125: }
! 11126: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
! 11127: if( iSid>mx ) mx = iSid;
! 11128: if( iSid!=k ) continue;
! 11129: if( n==0 ){
! 11130: rEstLoop = (double)nLoop;
! 11131: if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
! 11132: }
! 11133: n++;
! 11134: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
! 11135: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
! 11136: sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
! 11137: utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
! 11138: rEstLoop *= rEst;
! 11139: raw_printf(pArg->out,
! 11140: " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
! 11141: nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
! 11142: );
! 11143: }
! 11144: }
! 11145: raw_printf(pArg->out, "---------------------------\n");
! 11146: #endif
! 11147: }
! 11148:
! 11149: /*
! 11150: ** Parameter azArray points to a zero-terminated array of strings. zStr
! 11151: ** points to a single nul-terminated string. Return non-zero if zStr
! 11152: ** is equal, according to strcmp(), to any of the strings in the array.
! 11153: ** Otherwise, return zero.
! 11154: */
! 11155: static int str_in_array(const char *zStr, const char **azArray){
! 11156: int i;
! 11157: for(i=0; azArray[i]; i++){
! 11158: if( 0==strcmp(zStr, azArray[i]) ) return 1;
! 11159: }
! 11160: return 0;
! 11161: }
! 11162:
! 11163: /*
! 11164: ** If compiled statement pSql appears to be an EXPLAIN statement, allocate
! 11165: ** and populate the ShellState.aiIndent[] array with the number of
! 11166: ** spaces each opcode should be indented before it is output.
! 11167: **
! 11168: ** The indenting rules are:
! 11169: **
! 11170: ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
! 11171: ** all opcodes that occur between the p2 jump destination and the opcode
! 11172: ** itself by 2 spaces.
! 11173: **
! 11174: ** * For each "Goto", if the jump destination is earlier in the program
! 11175: ** and ends on one of:
! 11176: ** Yield SeekGt SeekLt RowSetRead Rewind
! 11177: ** or if the P1 parameter is one instead of zero,
! 11178: ** then indent all opcodes between the earlier instruction
! 11179: ** and "Goto" by 2 spaces.
! 11180: */
! 11181: static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
! 11182: const char *zSql; /* The text of the SQL statement */
! 11183: const char *z; /* Used to check if this is an EXPLAIN */
! 11184: int *abYield = 0; /* True if op is an OP_Yield */
! 11185: int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
! 11186: int iOp; /* Index of operation in p->aiIndent[] */
! 11187:
! 11188: const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
! 11189: const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
! 11190: "Rewind", 0 };
! 11191: const char *azGoto[] = { "Goto", 0 };
! 11192:
! 11193: /* Try to figure out if this is really an EXPLAIN statement. If this
! 11194: ** cannot be verified, return early. */
! 11195: if( sqlite3_column_count(pSql)!=8 ){
! 11196: p->cMode = p->mode;
! 11197: return;
! 11198: }
! 11199: zSql = sqlite3_sql(pSql);
! 11200: if( zSql==0 ) return;
! 11201: for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
! 11202: if( sqlite3_strnicmp(z, "explain", 7) ){
! 11203: p->cMode = p->mode;
! 11204: return;
! 11205: }
! 11206:
! 11207: for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
! 11208: int i;
! 11209: int iAddr = sqlite3_column_int(pSql, 0);
! 11210: const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
! 11211:
! 11212: /* Set p2 to the P2 field of the current opcode. Then, assuming that
! 11213: ** p2 is an instruction address, set variable p2op to the index of that
! 11214: ** instruction in the aiIndent[] array. p2 and p2op may be different if
! 11215: ** the current instruction is part of a sub-program generated by an
! 11216: ** SQL trigger or foreign key. */
! 11217: int p2 = sqlite3_column_int(pSql, 3);
! 11218: int p2op = (p2 + (iOp-iAddr));
! 11219:
! 11220: /* Grow the p->aiIndent array as required */
! 11221: if( iOp>=nAlloc ){
! 11222: if( iOp==0 ){
! 11223: /* Do further verfication that this is explain output. Abort if
! 11224: ** it is not */
! 11225: static const char *explainCols[] = {
! 11226: "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
! 11227: int jj;
! 11228: for(jj=0; jj<ArraySize(explainCols); jj++){
! 11229: if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
! 11230: p->cMode = p->mode;
! 11231: sqlite3_reset(pSql);
! 11232: return;
! 11233: }
! 11234: }
! 11235: }
! 11236: nAlloc += 100;
! 11237: p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
! 11238: if( p->aiIndent==0 ) shell_out_of_memory();
! 11239: abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
! 11240: if( abYield==0 ) shell_out_of_memory();
! 11241: }
! 11242: abYield[iOp] = str_in_array(zOp, azYield);
! 11243: p->aiIndent[iOp] = 0;
! 11244: p->nIndent = iOp+1;
! 11245:
! 11246: if( str_in_array(zOp, azNext) ){
! 11247: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
! 11248: }
! 11249: if( str_in_array(zOp, azGoto) && p2op<p->nIndent
! 11250: && (abYield[p2op] || sqlite3_column_int(pSql, 2))
! 11251: ){
! 11252: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
! 11253: }
! 11254: }
! 11255:
! 11256: p->iIndent = 0;
! 11257: sqlite3_free(abYield);
! 11258: sqlite3_reset(pSql);
! 11259: }
! 11260:
! 11261: /*
! 11262: ** Free the array allocated by explain_data_prepare().
! 11263: */
! 11264: static void explain_data_delete(ShellState *p){
! 11265: sqlite3_free(p->aiIndent);
! 11266: p->aiIndent = 0;
! 11267: p->nIndent = 0;
! 11268: p->iIndent = 0;
! 11269: }
! 11270:
! 11271: /*
! 11272: ** Disable and restore .wheretrace and .selecttrace settings.
! 11273: */
! 11274: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
! 11275: extern int sqlite3SelectTrace;
! 11276: static int savedSelectTrace;
! 11277: #endif
! 11278: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
! 11279: extern int sqlite3WhereTrace;
! 11280: static int savedWhereTrace;
! 11281: #endif
! 11282: static void disable_debug_trace_modes(void){
! 11283: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
! 11284: savedSelectTrace = sqlite3SelectTrace;
! 11285: sqlite3SelectTrace = 0;
! 11286: #endif
! 11287: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
! 11288: savedWhereTrace = sqlite3WhereTrace;
! 11289: sqlite3WhereTrace = 0;
! 11290: #endif
! 11291: }
! 11292: static void restore_debug_trace_modes(void){
! 11293: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
! 11294: sqlite3SelectTrace = savedSelectTrace;
! 11295: #endif
! 11296: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
! 11297: sqlite3WhereTrace = savedWhereTrace;
! 11298: #endif
! 11299: }
! 11300:
! 11301: /* Create the TEMP table used to store parameter bindings */
! 11302: static void bind_table_init(ShellState *p){
! 11303: int wrSchema = 0;
! 11304: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
! 11305: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
! 11306: sqlite3_exec(p->db,
! 11307: "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
! 11308: " key TEXT PRIMARY KEY,\n"
! 11309: " value ANY\n"
! 11310: ") WITHOUT ROWID;",
! 11311: 0, 0, 0);
! 11312: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
! 11313: }
! 11314:
! 11315: /*
! 11316: ** Bind parameters on a prepared statement.
! 11317: **
! 11318: ** Parameter bindings are taken from a TEMP table of the form:
! 11319: **
! 11320: ** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
! 11321: ** WITHOUT ROWID;
! 11322: **
! 11323: ** No bindings occur if this table does not exist. The special character '$'
! 11324: ** is included in the table name to help prevent collisions with actual tables.
! 11325: ** The table must be in the TEMP schema.
! 11326: */
! 11327: static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
! 11328: int nVar;
! 11329: int i;
! 11330: int rc;
! 11331: sqlite3_stmt *pQ = 0;
! 11332:
! 11333: nVar = sqlite3_bind_parameter_count(pStmt);
! 11334: if( nVar==0 ) return; /* Nothing to do */
! 11335: if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
! 11336: "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
! 11337: return; /* Parameter table does not exist */
! 11338: }
! 11339: rc = sqlite3_prepare_v2(pArg->db,
! 11340: "SELECT value FROM temp.sqlite_parameters"
! 11341: " WHERE key=?1", -1, &pQ, 0);
! 11342: if( rc || pQ==0 ) return;
! 11343: for(i=1; i<=nVar; i++){
! 11344: char zNum[30];
! 11345: const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
! 11346: if( zVar==0 ){
! 11347: sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
! 11348: zVar = zNum;
! 11349: }
! 11350: sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
! 11351: if( sqlite3_step(pQ)==SQLITE_ROW ){
! 11352: sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
! 11353: }else{
! 11354: sqlite3_bind_null(pStmt, i);
! 11355: }
! 11356: sqlite3_reset(pQ);
! 11357: }
! 11358: sqlite3_finalize(pQ);
! 11359: }
! 11360:
! 11361: /*
! 11362: ** Run a prepared statement
! 11363: */
! 11364: static void exec_prepared_stmt(
! 11365: ShellState *pArg, /* Pointer to ShellState */
! 11366: sqlite3_stmt *pStmt /* Statment to run */
! 11367: ){
! 11368: int rc;
! 11369:
! 11370: /* perform the first step. this will tell us if we
! 11371: ** have a result set or not and how wide it is.
! 11372: */
! 11373: rc = sqlite3_step(pStmt);
! 11374: /* if we have a result set... */
! 11375: if( SQLITE_ROW == rc ){
! 11376: /* allocate space for col name ptr, value ptr, and type */
! 11377: int nCol = sqlite3_column_count(pStmt);
! 11378: void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
! 11379: if( !pData ){
! 11380: rc = SQLITE_NOMEM;
! 11381: }else{
! 11382: char **azCols = (char **)pData; /* Names of result columns */
! 11383: char **azVals = &azCols[nCol]; /* Results */
! 11384: int *aiTypes = (int *)&azVals[nCol]; /* Result types */
! 11385: int i, x;
! 11386: assert(sizeof(int) <= sizeof(char *));
! 11387: /* save off ptrs to column names */
! 11388: for(i=0; i<nCol; i++){
! 11389: azCols[i] = (char *)sqlite3_column_name(pStmt, i);
! 11390: }
! 11391: do{
! 11392: /* extract the data and data types */
! 11393: for(i=0; i<nCol; i++){
! 11394: aiTypes[i] = x = sqlite3_column_type(pStmt, i);
! 11395: if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
! 11396: azVals[i] = "";
! 11397: }else{
! 11398: azVals[i] = (char*)sqlite3_column_text(pStmt, i);
! 11399: }
! 11400: if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
! 11401: rc = SQLITE_NOMEM;
! 11402: break; /* from for */
! 11403: }
! 11404: } /* end for */
! 11405:
! 11406: /* if data and types extracted successfully... */
! 11407: if( SQLITE_ROW == rc ){
! 11408: /* call the supplied callback with the result row data */
! 11409: if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
! 11410: rc = SQLITE_ABORT;
! 11411: }else{
! 11412: rc = sqlite3_step(pStmt);
! 11413: }
! 11414: }
! 11415: } while( SQLITE_ROW == rc );
! 11416: sqlite3_free(pData);
! 11417: }
! 11418: }
! 11419: }
! 11420:
! 11421: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 11422: /*
! 11423: ** This function is called to process SQL if the previous shell command
! 11424: ** was ".expert". It passes the SQL in the second argument directly to
! 11425: ** the sqlite3expert object.
! 11426: **
! 11427: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
! 11428: ** code. In this case, (*pzErr) may be set to point to a buffer containing
! 11429: ** an English language error message. It is the responsibility of the
! 11430: ** caller to eventually free this buffer using sqlite3_free().
! 11431: */
! 11432: static int expertHandleSQL(
! 11433: ShellState *pState,
! 11434: const char *zSql,
! 11435: char **pzErr
! 11436: ){
! 11437: assert( pState->expert.pExpert );
! 11438: assert( pzErr==0 || *pzErr==0 );
! 11439: return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
! 11440: }
! 11441:
! 11442: /*
! 11443: ** This function is called either to silently clean up the object
! 11444: ** created by the ".expert" command (if bCancel==1), or to generate a
! 11445: ** report from it and then clean it up (if bCancel==0).
! 11446: **
! 11447: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
! 11448: ** code. In this case, (*pzErr) may be set to point to a buffer containing
! 11449: ** an English language error message. It is the responsibility of the
! 11450: ** caller to eventually free this buffer using sqlite3_free().
! 11451: */
! 11452: static int expertFinish(
! 11453: ShellState *pState,
! 11454: int bCancel,
! 11455: char **pzErr
! 11456: ){
! 11457: int rc = SQLITE_OK;
! 11458: sqlite3expert *p = pState->expert.pExpert;
! 11459: assert( p );
! 11460: assert( bCancel || pzErr==0 || *pzErr==0 );
! 11461: if( bCancel==0 ){
! 11462: FILE *out = pState->out;
! 11463: int bVerbose = pState->expert.bVerbose;
! 11464:
! 11465: rc = sqlite3_expert_analyze(p, pzErr);
! 11466: if( rc==SQLITE_OK ){
! 11467: int nQuery = sqlite3_expert_count(p);
! 11468: int i;
! 11469:
! 11470: if( bVerbose ){
! 11471: const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
! 11472: raw_printf(out, "-- Candidates -----------------------------\n");
! 11473: raw_printf(out, "%s\n", zCand);
! 11474: }
! 11475: for(i=0; i<nQuery; i++){
! 11476: const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
! 11477: const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
! 11478: const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
! 11479: if( zIdx==0 ) zIdx = "(no new indexes)\n";
! 11480: if( bVerbose ){
! 11481: raw_printf(out, "-- Query %d --------------------------------\n",i+1);
! 11482: raw_printf(out, "%s\n\n", zSql);
! 11483: }
! 11484: raw_printf(out, "%s\n", zIdx);
! 11485: raw_printf(out, "%s\n", zEQP);
! 11486: }
! 11487: }
! 11488: }
! 11489: sqlite3_expert_destroy(p);
! 11490: pState->expert.pExpert = 0;
! 11491: return rc;
! 11492: }
! 11493:
! 11494: /*
! 11495: ** Implementation of ".expert" dot command.
! 11496: */
! 11497: static int expertDotCommand(
! 11498: ShellState *pState, /* Current shell tool state */
! 11499: char **azArg, /* Array of arguments passed to dot command */
! 11500: int nArg /* Number of entries in azArg[] */
! 11501: ){
! 11502: int rc = SQLITE_OK;
! 11503: char *zErr = 0;
! 11504: int i;
! 11505: int iSample = 0;
! 11506:
! 11507: assert( pState->expert.pExpert==0 );
! 11508: memset(&pState->expert, 0, sizeof(ExpertInfo));
! 11509:
! 11510: for(i=1; rc==SQLITE_OK && i<nArg; i++){
! 11511: char *z = azArg[i];
! 11512: int n;
! 11513: if( z[0]=='-' && z[1]=='-' ) z++;
! 11514: n = strlen30(z);
! 11515: if( n>=2 && 0==strncmp(z, "-verbose", n) ){
! 11516: pState->expert.bVerbose = 1;
! 11517: }
! 11518: else if( n>=2 && 0==strncmp(z, "-sample", n) ){
! 11519: if( i==(nArg-1) ){
! 11520: raw_printf(stderr, "option requires an argument: %s\n", z);
! 11521: rc = SQLITE_ERROR;
! 11522: }else{
! 11523: iSample = (int)integerValue(azArg[++i]);
! 11524: if( iSample<0 || iSample>100 ){
! 11525: raw_printf(stderr, "value out of range: %s\n", azArg[i]);
! 11526: rc = SQLITE_ERROR;
! 11527: }
! 11528: }
! 11529: }
! 11530: else{
! 11531: raw_printf(stderr, "unknown option: %s\n", z);
! 11532: rc = SQLITE_ERROR;
! 11533: }
! 11534: }
! 11535:
! 11536: if( rc==SQLITE_OK ){
! 11537: pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
! 11538: if( pState->expert.pExpert==0 ){
! 11539: raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
! 11540: rc = SQLITE_ERROR;
! 11541: }else{
! 11542: sqlite3_expert_config(
! 11543: pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
! 11544: );
! 11545: }
! 11546: }
! 11547:
! 11548: return rc;
! 11549: }
! 11550: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
! 11551:
! 11552: /*
! 11553: ** Execute a statement or set of statements. Print
! 11554: ** any result rows/columns depending on the current mode
! 11555: ** set via the supplied callback.
! 11556: **
! 11557: ** This is very similar to SQLite's built-in sqlite3_exec()
! 11558: ** function except it takes a slightly different callback
! 11559: ** and callback data argument.
! 11560: */
! 11561: static int shell_exec(
! 11562: ShellState *pArg, /* Pointer to ShellState */
! 11563: const char *zSql, /* SQL to be evaluated */
! 11564: char **pzErrMsg /* Error msg written here */
! 11565: ){
! 11566: sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
! 11567: int rc = SQLITE_OK; /* Return Code */
! 11568: int rc2;
! 11569: const char *zLeftover; /* Tail of unprocessed SQL */
! 11570: sqlite3 *db = pArg->db;
! 11571:
! 11572: if( pzErrMsg ){
! 11573: *pzErrMsg = NULL;
! 11574: }
! 11575:
! 11576: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 11577: if( pArg->expert.pExpert ){
! 11578: rc = expertHandleSQL(pArg, zSql, pzErrMsg);
! 11579: return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
! 11580: }
! 11581: #endif
! 11582:
! 11583: while( zSql[0] && (SQLITE_OK == rc) ){
! 11584: static const char *zStmtSql;
! 11585: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
! 11586: if( SQLITE_OK != rc ){
! 11587: if( pzErrMsg ){
! 11588: *pzErrMsg = save_err_msg(db);
! 11589: }
! 11590: }else{
! 11591: if( !pStmt ){
! 11592: /* this happens for a comment or white-space */
! 11593: zSql = zLeftover;
! 11594: while( IsSpace(zSql[0]) ) zSql++;
! 11595: continue;
1.4 misho 11596: }
1.4.2.2 ! misho 11597: zStmtSql = sqlite3_sql(pStmt);
! 11598: if( zStmtSql==0 ) zStmtSql = "";
! 11599: while( IsSpace(zStmtSql[0]) ) zStmtSql++;
! 11600:
! 11601: /* save off the prepared statment handle and reset row count */
! 11602: if( pArg ){
! 11603: pArg->pStmt = pStmt;
! 11604: pArg->cnt = 0;
! 11605: }
! 11606:
! 11607: /* echo the sql statement if echo on */
! 11608: if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
! 11609: utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
! 11610: }
! 11611:
! 11612: /* Show the EXPLAIN QUERY PLAN if .eqp is on */
! 11613: if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
! 11614: sqlite3_stmt *pExplain;
! 11615: char *zEQP;
! 11616: int triggerEQP = 0;
! 11617: disable_debug_trace_modes();
! 11618: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
! 11619: if( pArg->autoEQP>=AUTOEQP_trigger ){
! 11620: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
! 11621: }
! 11622: zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
! 11623: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
! 11624: if( rc==SQLITE_OK ){
! 11625: while( sqlite3_step(pExplain)==SQLITE_ROW ){
! 11626: const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
! 11627: int iEqpId = sqlite3_column_int(pExplain, 0);
! 11628: int iParentId = sqlite3_column_int(pExplain, 1);
! 11629: if( zEQPLine[0]=='-' ) eqp_render(pArg);
! 11630: eqp_append(pArg, iEqpId, iParentId, zEQPLine);
1.4 misho 11631: }
1.4.2.2 ! misho 11632: eqp_render(pArg);
! 11633: }
! 11634: sqlite3_finalize(pExplain);
! 11635: sqlite3_free(zEQP);
! 11636: if( pArg->autoEQP>=AUTOEQP_full ){
! 11637: /* Also do an EXPLAIN for ".eqp full" mode */
! 11638: zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
! 11639: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
! 11640: if( rc==SQLITE_OK ){
! 11641: pArg->cMode = MODE_Explain;
! 11642: explain_data_prepare(pArg, pExplain);
! 11643: exec_prepared_stmt(pArg, pExplain);
! 11644: explain_data_delete(pArg);
1.4 misho 11645: }
1.4.2.2 ! misho 11646: sqlite3_finalize(pExplain);
! 11647: sqlite3_free(zEQP);
1.3 misho 11648: }
1.4.2.2 ! misho 11649: if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
! 11650: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
! 11651: /* Reprepare pStmt before reactiving trace modes */
! 11652: sqlite3_finalize(pStmt);
! 11653: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
! 11654: if( pArg ) pArg->pStmt = pStmt;
1.2 misho 11655: }
1.4.2.2 ! misho 11656: restore_debug_trace_modes();
1.2 misho 11657: }
1.4.2.2 ! misho 11658:
! 11659: if( pArg ){
! 11660: pArg->cMode = pArg->mode;
! 11661: if( pArg->autoExplain ){
! 11662: if( sqlite3_stmt_isexplain(pStmt)==1 ){
! 11663: pArg->cMode = MODE_Explain;
! 11664: }
! 11665: if( sqlite3_stmt_isexplain(pStmt)==2 ){
! 11666: pArg->cMode = MODE_EQP;
! 11667: }
1.2 misho 11668: }
1.4.2.2 ! misho 11669:
! 11670: /* If the shell is currently in ".explain" mode, gather the extra
! 11671: ** data required to add indents to the output.*/
! 11672: if( pArg->cMode==MODE_Explain ){
! 11673: explain_data_prepare(pArg, pStmt);
1.2 misho 11674: }
11675: }
1.4.2.2 ! misho 11676:
! 11677: bind_prepared_stmt(pArg, pStmt);
! 11678: exec_prepared_stmt(pArg, pStmt);
! 11679: explain_data_delete(pArg);
! 11680: eqp_render(pArg);
! 11681:
! 11682: /* print usage stats if stats on */
! 11683: if( pArg && pArg->statsOn ){
! 11684: display_stats(db, pArg, 0);
1.2 misho 11685: }
1.4.2.2 ! misho 11686:
! 11687: /* print loop-counters if required */
! 11688: if( pArg && pArg->scanstatsOn ){
! 11689: display_scanstats(db, pArg);
1.2 misho 11690: }
1.4.2.2 ! misho 11691:
! 11692: /* Finalize the statement just executed. If this fails, save a
! 11693: ** copy of the error message. Otherwise, set zSql to point to the
! 11694: ** next statement to execute. */
! 11695: rc2 = sqlite3_finalize(pStmt);
! 11696: if( rc!=SQLITE_NOMEM ) rc = rc2;
! 11697: if( rc==SQLITE_OK ){
! 11698: zSql = zLeftover;
! 11699: while( IsSpace(zSql[0]) ) zSql++;
! 11700: }else if( pzErrMsg ){
! 11701: *pzErrMsg = save_err_msg(db);
1.2 misho 11702: }
1.4.2.2 ! misho 11703:
! 11704: /* clear saved stmt handle */
! 11705: if( pArg ){
! 11706: pArg->pStmt = NULL;
1.2 misho 11707: }
11708: }
1.4.2.2 ! misho 11709: } /* end while */
! 11710:
! 11711: return rc;
! 11712: }
! 11713:
! 11714: /*
! 11715: ** Release memory previously allocated by tableColumnList().
! 11716: */
! 11717: static void freeColumnList(char **azCol){
! 11718: int i;
! 11719: for(i=1; azCol[i]; i++){
! 11720: sqlite3_free(azCol[i]);
! 11721: }
! 11722: /* azCol[0] is a static string */
! 11723: sqlite3_free(azCol);
! 11724: }
! 11725:
! 11726: /*
! 11727: ** Return a list of pointers to strings which are the names of all
! 11728: ** columns in table zTab. The memory to hold the names is dynamically
! 11729: ** allocated and must be released by the caller using a subsequent call
! 11730: ** to freeColumnList().
! 11731: **
! 11732: ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
! 11733: ** value that needs to be preserved, then azCol[0] is filled in with the
! 11734: ** name of the rowid column.
! 11735: **
! 11736: ** The first regular column in the table is azCol[1]. The list is terminated
! 11737: ** by an entry with azCol[i]==0.
! 11738: */
! 11739: static char **tableColumnList(ShellState *p, const char *zTab){
! 11740: char **azCol = 0;
! 11741: sqlite3_stmt *pStmt;
! 11742: char *zSql;
! 11743: int nCol = 0;
! 11744: int nAlloc = 0;
! 11745: int nPK = 0; /* Number of PRIMARY KEY columns seen */
! 11746: int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
! 11747: int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
! 11748: int rc;
! 11749:
! 11750: zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
! 11751: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
! 11752: sqlite3_free(zSql);
! 11753: if( rc ) return 0;
! 11754: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 11755: if( nCol>=nAlloc-2 ){
! 11756: nAlloc = nAlloc*2 + nCol + 10;
! 11757: azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
! 11758: if( azCol==0 ) shell_out_of_memory();
1.4.2.1 misho 11759: }
1.4.2.2 ! misho 11760: azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
! 11761: if( sqlite3_column_int(pStmt, 5) ){
! 11762: nPK++;
! 11763: if( nPK==1
! 11764: && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
! 11765: "INTEGER")==0
! 11766: ){
! 11767: isIPK = 1;
! 11768: }else{
! 11769: isIPK = 0;
1.2 misho 11770: }
1.4 misho 11771: }
1.4.2.2 ! misho 11772: }
! 11773: sqlite3_finalize(pStmt);
! 11774: if( azCol==0 ) return 0;
! 11775: azCol[0] = 0;
! 11776: azCol[nCol+1] = 0;
! 11777:
! 11778: /* The decision of whether or not a rowid really needs to be preserved
! 11779: ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
! 11780: ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
! 11781: ** rowids on tables where the rowid is inaccessible because there are other
! 11782: ** columns in the table named "rowid", "_rowid_", and "oid".
! 11783: */
! 11784: if( preserveRowid && isIPK ){
! 11785: /* If a single PRIMARY KEY column with type INTEGER was seen, then it
! 11786: ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
! 11787: ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
! 11788: ** ROWID aliases. To distinguish these cases, check to see if
! 11789: ** there is a "pk" entry in "PRAGMA index_list". There will be
! 11790: ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
! 11791: */
! 11792: zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
! 11793: " WHERE origin='pk'", zTab);
! 11794: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
! 11795: sqlite3_free(zSql);
! 11796: if( rc ){
! 11797: freeColumnList(azCol);
! 11798: return 0;
! 11799: }
! 11800: rc = sqlite3_step(pStmt);
! 11801: sqlite3_finalize(pStmt);
! 11802: preserveRowid = rc==SQLITE_ROW;
! 11803: }
! 11804: if( preserveRowid ){
! 11805: /* Only preserve the rowid if we can find a name to use for the
! 11806: ** rowid */
! 11807: static char *azRowid[] = { "rowid", "_rowid_", "oid" };
! 11808: int i, j;
! 11809: for(j=0; j<3; j++){
! 11810: for(i=1; i<=nCol; i++){
! 11811: if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
1.4 misho 11812: }
1.4.2.2 ! misho 11813: if( i>nCol ){
! 11814: /* At this point, we know that azRowid[j] is not the name of any
! 11815: ** ordinary column in the table. Verify that azRowid[j] is a valid
! 11816: ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
! 11817: ** tables will fail this last check */
! 11818: rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
! 11819: if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
! 11820: break;
1.4 misho 11821: }
1.2 misho 11822: }
11823: }
1.4.2.2 ! misho 11824: return azCol;
1.2 misho 11825: }
11826:
11827: /*
1.4.2.2 ! misho 11828: ** Toggle the reverse_unordered_selects setting.
1.2 misho 11829: */
1.4.2.2 ! misho 11830: static void toggleSelectOrder(sqlite3 *db){
! 11831: sqlite3_stmt *pStmt = 0;
! 11832: int iSetting = 0;
! 11833: char zStmt[100];
! 11834: sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
! 11835: if( sqlite3_step(pStmt)==SQLITE_ROW ){
! 11836: iSetting = sqlite3_column_int(pStmt, 0);
! 11837: }
! 11838: sqlite3_finalize(pStmt);
! 11839: sqlite3_snprintf(sizeof(zStmt), zStmt,
! 11840: "PRAGMA reverse_unordered_selects(%d)", !iSetting);
! 11841: sqlite3_exec(db, zStmt, 0, 0, 0);
1.2 misho 11842: }
11843:
11844: /*
1.4.2.2 ! misho 11845: ** This is a different callback routine used for dumping the database.
! 11846: ** Each row received by this callback consists of a table name,
! 11847: ** the table type ("index" or "table") and SQL to create the table.
! 11848: ** This routine should print text sufficient to recreate the table.
1.4.2.1 misho 11849: */
1.4.2.2 ! misho 11850: static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
! 11851: int rc;
! 11852: const char *zTable;
! 11853: const char *zType;
! 11854: const char *zSql;
! 11855: ShellState *p = (ShellState *)pArg;
! 11856:
! 11857: UNUSED_PARAMETER(azNotUsed);
! 11858: if( nArg!=3 || azArg==0 ) return 0;
! 11859: zTable = azArg[0];
! 11860: zType = azArg[1];
! 11861: zSql = azArg[2];
! 11862:
! 11863: if( strcmp(zTable, "sqlite_sequence")==0 ){
! 11864: raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
! 11865: }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
! 11866: raw_printf(p->out, "ANALYZE sqlite_master;\n");
! 11867: }else if( strncmp(zTable, "sqlite_", 7)==0 ){
! 11868: return 0;
! 11869: }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
! 11870: char *zIns;
! 11871: if( !p->writableSchema ){
! 11872: raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
! 11873: p->writableSchema = 1;
! 11874: }
! 11875: zIns = sqlite3_mprintf(
! 11876: "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
! 11877: "VALUES('table','%q','%q',0,'%q');",
! 11878: zTable, zTable, zSql);
! 11879: utf8_printf(p->out, "%s\n", zIns);
! 11880: sqlite3_free(zIns);
! 11881: return 0;
! 11882: }else{
! 11883: printSchemaLine(p->out, zSql, ";\n");
1.4.2.1 misho 11884: }
11885:
1.4.2.2 ! misho 11886: if( strcmp(zType, "table")==0 ){
! 11887: ShellText sSelect;
! 11888: ShellText sTable;
! 11889: char **azCol;
! 11890: int i;
! 11891: char *savedDestTable;
! 11892: int savedMode;
! 11893:
! 11894: azCol = tableColumnList(p, zTable);
! 11895: if( azCol==0 ){
! 11896: p->nErr++;
! 11897: return 0;
! 11898: }
! 11899:
! 11900: /* Always quote the table name, even if it appears to be pure ascii,
! 11901: ** in case it is a keyword. Ex: INSERT INTO "table" ... */
! 11902: initText(&sTable);
! 11903: appendText(&sTable, zTable, quoteChar(zTable));
! 11904: /* If preserving the rowid, add a column list after the table name.
! 11905: ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
! 11906: ** instead of the usual "INSERT INTO tab VALUES(...)".
! 11907: */
! 11908: if( azCol[0] ){
! 11909: appendText(&sTable, "(", 0);
! 11910: appendText(&sTable, azCol[0], 0);
! 11911: for(i=1; azCol[i]; i++){
! 11912: appendText(&sTable, ",", 0);
! 11913: appendText(&sTable, azCol[i], quoteChar(azCol[i]));
! 11914: }
! 11915: appendText(&sTable, ")", 0);
! 11916: }
! 11917:
! 11918: /* Build an appropriate SELECT statement */
! 11919: initText(&sSelect);
! 11920: appendText(&sSelect, "SELECT ", 0);
! 11921: if( azCol[0] ){
! 11922: appendText(&sSelect, azCol[0], 0);
! 11923: appendText(&sSelect, ",", 0);
! 11924: }
! 11925: for(i=1; azCol[i]; i++){
! 11926: appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
! 11927: if( azCol[i+1] ){
! 11928: appendText(&sSelect, ",", 0);
! 11929: }
! 11930: }
! 11931: freeColumnList(azCol);
! 11932: appendText(&sSelect, " FROM ", 0);
! 11933: appendText(&sSelect, zTable, quoteChar(zTable));
! 11934:
! 11935: savedDestTable = p->zDestTable;
! 11936: savedMode = p->mode;
! 11937: p->zDestTable = sTable.z;
! 11938: p->mode = p->cMode = MODE_Insert;
! 11939: rc = shell_exec(p, sSelect.z, 0);
! 11940: if( (rc&0xff)==SQLITE_CORRUPT ){
! 11941: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
! 11942: toggleSelectOrder(p->db);
! 11943: shell_exec(p, sSelect.z, 0);
! 11944: toggleSelectOrder(p->db);
! 11945: }
! 11946: p->zDestTable = savedDestTable;
! 11947: p->mode = savedMode;
! 11948: freeText(&sTable);
! 11949: freeText(&sSelect);
! 11950: if( rc ) p->nErr++;
1.4.2.1 misho 11951: }
1.4.2.2 ! misho 11952: return 0;
1.4.2.1 misho 11953: }
11954:
11955: /*
1.4.2.2 ! misho 11956: ** Run zQuery. Use dump_callback() as the callback routine so that
! 11957: ** the contents of the query are output as SQL statements.
! 11958: **
! 11959: ** If we get a SQLITE_CORRUPT error, rerun the query after appending
! 11960: ** "ORDER BY rowid DESC" to the end.
1.2 misho 11961: */
1.4.2.2 ! misho 11962: static int run_schema_dump_query(
! 11963: ShellState *p,
! 11964: const char *zQuery
! 11965: ){
! 11966: int rc;
! 11967: char *zErr = 0;
! 11968: rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
! 11969: if( rc==SQLITE_CORRUPT ){
! 11970: char *zQ2;
! 11971: int len = strlen30(zQuery);
! 11972: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
! 11973: if( zErr ){
! 11974: utf8_printf(p->out, "/****** %s ******/\n", zErr);
! 11975: sqlite3_free(zErr);
! 11976: zErr = 0;
! 11977: }
! 11978: zQ2 = malloc( len+100 );
! 11979: if( zQ2==0 ) return rc;
! 11980: sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
! 11981: rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
! 11982: if( rc ){
! 11983: utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
! 11984: }else{
! 11985: rc = SQLITE_CORRUPT;
! 11986: }
! 11987: sqlite3_free(zErr);
! 11988: free(zQ2);
1.2 misho 11989: }
1.4.2.2 ! misho 11990: return rc;
1.2 misho 11991: }
11992:
1.4.2.2 ! misho 11993: /*
! 11994: ** Text of help messages.
! 11995: **
! 11996: ** The help text for each individual command begins with a line that starts
! 11997: ** with ".". Subsequent lines are supplimental information.
! 11998: **
! 11999: ** There must be two or more spaces between the end of the command and the
! 12000: ** start of the description of what that command does.
! 12001: */
! 12002: static const char *(azHelp[]) = {
! 12003: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
! 12004: ".archive ... Manage SQL archives",
! 12005: " Each command must have exactly one of the following options:",
! 12006: " -c, --create Create a new archive",
! 12007: " -u, --update Add files or update files with changed mtime",
! 12008: " -i, --insert Like -u but always add even if mtime unchanged",
! 12009: " -t, --list List contents of archive",
! 12010: " -x, --extract Extract files from archive",
! 12011: " Optional arguments:",
! 12012: " -v, --verbose Print each filename as it is processed",
! 12013: " -f FILE, --file FILE Operate on archive FILE (default is current db)",
! 12014: " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
! 12015: " -C DIR, --directory DIR Change to directory DIR to read/extract files",
! 12016: " -n, --dryrun Show the SQL that would have occurred",
! 12017: " Examples:",
! 12018: " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
! 12019: " .ar -tf archive.sar # List members of archive.sar",
! 12020: " .ar -xvf archive.sar # Verbosely extract files from archive.sar",
! 12021: " See also:",
! 12022: " http://sqlite.org/cli.html#sqlar_archive_support",
! 12023: #endif
! 12024: #ifndef SQLITE_OMIT_AUTHORIZATION
! 12025: ".auth ON|OFF Show authorizer callbacks",
! 12026: #endif
! 12027: ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
! 12028: " --append Use the appendvfs",
! 12029: " --async Write to FILE without a journal and without fsync()",
! 12030: ".bail on|off Stop after hitting an error. Default OFF",
! 12031: ".binary on|off Turn binary output on or off. Default OFF",
! 12032: ".cd DIRECTORY Change the working directory to DIRECTORY",
! 12033: ".changes on|off Show number of rows changed by SQL",
! 12034: ".check GLOB Fail if output since .testcase does not match",
! 12035: ".clone NEWDB Clone data into NEWDB from the existing database",
! 12036: ".databases List names and files of attached databases",
! 12037: ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
! 12038: ".dbinfo ?DB? Show status information about the database",
! 12039: ".dump ?TABLE? ... Render all database content as SQL",
! 12040: " Options:",
! 12041: " --preserve-rowids Include ROWID values in the output",
! 12042: " --newlines Allow unescaped newline characters in output",
! 12043: " TABLE is a LIKE pattern for the tables to dump",
! 12044: ".echo on|off Turn command echo on or off",
! 12045: ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
! 12046: " Other Modes:",
! 12047: #ifdef SQLITE_DEBUG
! 12048: " test Show raw EXPLAIN QUERY PLAN output",
! 12049: " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
! 12050: #endif
! 12051: " trigger Like \"full\" but also show trigger bytecode",
! 12052: ".excel Display the output of next command in a spreadsheet",
! 12053: ".exit ?CODE? Exit this program with return-code CODE",
! 12054: ".expert EXPERIMENTAL. Suggest indexes for specified queries",
! 12055: /* Because explain mode comes on automatically now, the ".explain" mode
! 12056: ** is removed from the help screen. It is still supported for legacy, however */
! 12057: /*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
! 12058: ".filectrl CMD ... Run various sqlite3_file_control() operations",
! 12059: " Run \".filectrl\" with no arguments for details",
! 12060: ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
! 12061: ".headers on|off Turn display of headers on or off",
! 12062: ".help ?-all? ?PATTERN? Show help text for PATTERN",
! 12063: ".import FILE TABLE Import data from FILE into TABLE",
! 12064: #ifndef SQLITE_OMIT_TEST_CONTROL
! 12065: ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
! 12066: #endif
! 12067: ".indexes ?TABLE? Show names of indexes",
! 12068: " If TABLE is specified, only show indexes for",
! 12069: " tables matching TABLE using the LIKE operator.",
! 12070: #ifdef SQLITE_ENABLE_IOTRACE
! 12071: ".iotrace FILE Enable I/O diagnostic logging to FILE",
! 12072: #endif
! 12073: ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
! 12074: ".lint OPTIONS Report potential schema issues.",
! 12075: " Options:",
! 12076: " fkey-indexes Find missing foreign key indexes",
! 12077: #ifndef SQLITE_OMIT_LOAD_EXTENSION
! 12078: ".load FILE ?ENTRY? Load an extension library",
! 12079: #endif
! 12080: ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
! 12081: ".mode MODE ?TABLE? Set output mode",
! 12082: " MODE is one of:",
! 12083: " ascii Columns/rows delimited by 0x1F and 0x1E",
! 12084: " csv Comma-separated values",
! 12085: " column Left-aligned columns. (See .width)",
! 12086: " html HTML <table> code",
! 12087: " insert SQL insert statements for TABLE",
! 12088: " line One value per line",
! 12089: " list Values delimited by \"|\"",
! 12090: " quote Escape answers as for SQL",
! 12091: " tabs Tab-separated values",
! 12092: " tcl TCL list elements",
! 12093: ".nullvalue STRING Use STRING in place of NULL values",
! 12094: ".once (-e|-x|FILE) Output for the next SQL command only to FILE",
! 12095: " If FILE begins with '|' then open as a pipe",
! 12096: " Other options:",
! 12097: " -e Invoke system text editor",
! 12098: " -x Open in a spreadsheet",
! 12099: ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
! 12100: " Options:",
! 12101: " --append Use appendvfs to append database to the end of FILE",
! 12102: #ifdef SQLITE_ENABLE_DESERIALIZE
! 12103: " --deserialize Load into memory useing sqlite3_deserialize()",
! 12104: " --hexdb Load the output of \"dbtotxt\" as an in-memory database",
! 12105: " --maxsize N Maximum size for --hexdb or --deserialized database",
! 12106: #endif
! 12107: " --new Initialize FILE to an empty database",
! 12108: " --readonly Open FILE readonly",
! 12109: " --zip FILE is a ZIP archive",
! 12110: ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
! 12111: " If FILE begins with '|' then open it as a pipe.",
! 12112: ".parameter CMD ... Manage SQL parameter bindings",
! 12113: " clear Erase all bindings",
! 12114: " init Initialize the TEMP table that holds bindings",
! 12115: " list List the current parameter bindings",
! 12116: " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
! 12117: " PARAMETER should start with '$', ':', '@', or '?'",
! 12118: " unset PARAMETER Remove PARAMETER from the binding table",
! 12119: ".print STRING... Print literal STRING",
! 12120: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
! 12121: ".progress N Invoke progress handler after every N opcodes",
! 12122: " --limit N Interrupt after N progress callbacks",
! 12123: " --once Do no more than one progress interrupt",
! 12124: " --quiet|-q No output except at interrupts",
! 12125: " --reset Reset the count for each input and interrupt",
! 12126: #endif
! 12127: ".prompt MAIN CONTINUE Replace the standard prompts",
! 12128: ".quit Exit this program",
! 12129: ".read FILE Read input from FILE",
! 12130: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 12131: ".recover Recover as much data as possible from corrupt db.",
! 12132: #endif
! 12133: ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
! 12134: ".save FILE Write in-memory database into FILE",
! 12135: ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
! 12136: ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
! 12137: " Options:",
! 12138: " --indent Try to pretty-print the schema",
! 12139: ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
! 12140: " Options:",
! 12141: " --init Create a new SELFTEST table",
! 12142: " -v Verbose output",
! 12143: ".separator COL ?ROW? Change the column and row separators",
! 12144: #if defined(SQLITE_ENABLE_SESSION)
! 12145: ".session ?NAME? CMD ... Create or control sessions",
! 12146: " Subcommands:",
! 12147: " attach TABLE Attach TABLE",
! 12148: " changeset FILE Write a changeset into FILE",
! 12149: " close Close one session",
! 12150: " enable ?BOOLEAN? Set or query the enable bit",
! 12151: " filter GLOB... Reject tables matching GLOBs",
! 12152: " indirect ?BOOLEAN? Mark or query the indirect status",
! 12153: " isempty Query whether the session is empty",
! 12154: " list List currently open session names",
! 12155: " open DB NAME Open a new session on DB",
! 12156: " patchset FILE Write a patchset into FILE",
! 12157: " If ?NAME? is omitted, the first defined session is used.",
! 12158: #endif
! 12159: ".sha3sum ... Compute a SHA3 hash of database content",
! 12160: " Options:",
! 12161: " --schema Also hash the sqlite_master table",
! 12162: " --sha3-224 Use the sha3-224 algorithm",
! 12163: " --sha3-256 Use the sha3-256 algorithm. This is the default.",
! 12164: " --sha3-384 Use the sha3-384 algorithm",
! 12165: " --sha3-512 Use the sha3-512 algorithm",
! 12166: " Any other argument is a LIKE pattern for tables to hash",
! 12167: #ifndef SQLITE_NOHAVE_SYSTEM
! 12168: ".shell CMD ARGS... Run CMD ARGS... in a system shell",
! 12169: #endif
! 12170: ".show Show the current values for various settings",
! 12171: ".stats ?on|off? Show stats or turn stats on or off",
! 12172: #ifndef SQLITE_NOHAVE_SYSTEM
! 12173: ".system CMD ARGS... Run CMD ARGS... in a system shell",
! 12174: #endif
! 12175: ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
! 12176: ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
! 12177: ".testctrl CMD ... Run various sqlite3_test_control() operations",
! 12178: " Run \".testctrl\" with no arguments for details",
! 12179: ".timeout MS Try opening locked tables for MS milliseconds",
! 12180: ".timer on|off Turn SQL timer on or off",
! 12181: #ifndef SQLITE_OMIT_TRACE
! 12182: ".trace ?OPTIONS? Output each SQL statement as it is run",
! 12183: " FILE Send output to FILE",
! 12184: " stdout Send output to stdout",
! 12185: " stderr Send output to stderr",
! 12186: " off Disable tracing",
! 12187: " --expanded Expand query parameters",
! 12188: #ifdef SQLITE_ENABLE_NORMALIZE
! 12189: " --normalized Normal the SQL statements",
! 12190: #endif
! 12191: " --plain Show SQL as it is input",
! 12192: " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
! 12193: " --profile Profile statements (SQLITE_TRACE_PROFILE)",
! 12194: " --row Trace each row (SQLITE_TRACE_ROW)",
! 12195: " --close Trace connection close (SQLITE_TRACE_CLOSE)",
! 12196: #endif /* SQLITE_OMIT_TRACE */
! 12197: ".vfsinfo ?AUX? Information about the top-level VFS",
! 12198: ".vfslist List all available VFSes",
! 12199: ".vfsname ?AUX? Print the name of the VFS stack",
! 12200: ".width NUM1 NUM2 ... Set column widths for \"column\" mode",
! 12201: " Negative values right-justify",
! 12202: };
1.2 misho 12203:
12204: /*
1.4.2.2 ! misho 12205: ** Output help text.
1.2 misho 12206: **
1.4.2.2 ! misho 12207: ** zPattern describes the set of commands for which help text is provided.
! 12208: ** If zPattern is NULL, then show all commands, but only give a one-line
! 12209: ** description of each.
! 12210: **
! 12211: ** Return the number of matches.
1.2 misho 12212: */
1.4.2.2 ! misho 12213: static int showHelp(FILE *out, const char *zPattern){
! 12214: int i = 0;
! 12215: int j = 0;
! 12216: int n = 0;
! 12217: char *zPat;
! 12218: if( zPattern==0
! 12219: || zPattern[0]=='0'
! 12220: || strcmp(zPattern,"-a")==0
! 12221: || strcmp(zPattern,"-all")==0
! 12222: ){
! 12223: /* Show all commands, but only one line per command */
! 12224: if( zPattern==0 ) zPattern = "";
! 12225: for(i=0; i<ArraySize(azHelp); i++){
! 12226: if( azHelp[i][0]=='.' || zPattern[0] ){
! 12227: utf8_printf(out, "%s\n", azHelp[i]);
! 12228: n++;
! 12229: }
1.2 misho 12230: }
1.4.2.2 ! misho 12231: }else{
! 12232: /* Look for commands that for which zPattern is an exact prefix */
! 12233: zPat = sqlite3_mprintf(".%s*", zPattern);
! 12234: for(i=0; i<ArraySize(azHelp); i++){
! 12235: if( sqlite3_strglob(zPat, azHelp[i])==0 ){
! 12236: utf8_printf(out, "%s\n", azHelp[i]);
! 12237: j = i+1;
! 12238: n++;
! 12239: }
! 12240: }
! 12241: sqlite3_free(zPat);
! 12242: if( n ){
! 12243: if( n==1 ){
! 12244: /* when zPattern is a prefix of exactly one command, then include the
! 12245: ** details of that command, which should begin at offset j */
! 12246: while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
! 12247: utf8_printf(out, "%s\n", azHelp[j]);
! 12248: j++;
! 12249: }
! 12250: }
! 12251: return n;
1.3 misho 12252: }
1.4.2.2 ! misho 12253: /* Look for commands that contain zPattern anywhere. Show the complete
! 12254: ** text of all commands that match. */
! 12255: zPat = sqlite3_mprintf("%%%s%%", zPattern);
! 12256: for(i=0; i<ArraySize(azHelp); i++){
! 12257: if( azHelp[i][0]=='.' ) j = i;
! 12258: if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
! 12259: utf8_printf(out, "%s\n", azHelp[j]);
! 12260: while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
! 12261: j++;
! 12262: utf8_printf(out, "%s\n", azHelp[j]);
! 12263: }
! 12264: i = j;
! 12265: n++;
! 12266: }
1.4 misho 12267: }
1.4.2.2 ! misho 12268: sqlite3_free(zPat);
1.2 misho 12269: }
1.4.2.2 ! misho 12270: return n;
! 12271: }
! 12272:
! 12273: /* Forward reference */
! 12274: static int process_input(ShellState *p);
! 12275:
! 12276: /*
! 12277: ** Read the content of file zName into memory obtained from sqlite3_malloc64()
! 12278: ** and return a pointer to the buffer. The caller is responsible for freeing
! 12279: ** the memory.
! 12280: **
! 12281: ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
! 12282: ** read.
! 12283: **
! 12284: ** For convenience, a nul-terminator byte is always appended to the data read
! 12285: ** from the file before the buffer is returned. This byte is not included in
! 12286: ** the final value of (*pnByte), if applicable.
! 12287: **
! 12288: ** NULL is returned if any error is encountered. The final value of *pnByte
! 12289: ** is undefined in this case.
! 12290: */
! 12291: static char *readFile(const char *zName, int *pnByte){
! 12292: FILE *in = fopen(zName, "rb");
! 12293: long nIn;
! 12294: size_t nRead;
! 12295: char *pBuf;
! 12296: if( in==0 ) return 0;
! 12297: fseek(in, 0, SEEK_END);
! 12298: nIn = ftell(in);
! 12299: rewind(in);
! 12300: pBuf = sqlite3_malloc64( nIn+1 );
! 12301: if( pBuf==0 ){ fclose(in); return 0; }
! 12302: nRead = fread(pBuf, nIn, 1, in);
! 12303: fclose(in);
! 12304: if( nRead!=1 ){
! 12305: sqlite3_free(pBuf);
! 12306: return 0;
1.2 misho 12307: }
1.4.2.2 ! misho 12308: pBuf[nIn] = 0;
! 12309: if( pnByte ) *pnByte = nIn;
! 12310: return pBuf;
1.2 misho 12311: }
12312:
1.4.2.2 ! misho 12313: #if defined(SQLITE_ENABLE_SESSION)
1.2 misho 12314: /*
1.4.2.2 ! misho 12315: ** Close a single OpenSession object and release all of its associated
! 12316: ** resources.
1.2 misho 12317: */
1.4.2.2 ! misho 12318: static void session_close(OpenSession *pSession){
! 12319: int i;
! 12320: sqlite3session_delete(pSession->p);
! 12321: sqlite3_free(pSession->zName);
! 12322: for(i=0; i<pSession->nFilter; i++){
! 12323: sqlite3_free(pSession->azFilter[i]);
1.2 misho 12324: }
1.4.2.2 ! misho 12325: sqlite3_free(pSession->azFilter);
! 12326: memset(pSession, 0, sizeof(OpenSession));
1.2 misho 12327: }
1.4.2.2 ! misho 12328: #endif
1.2 misho 12329:
1.4 misho 12330: /*
1.4.2.2 ! misho 12331: ** Close all OpenSession objects and release all associated resources.
1.4 misho 12332: */
1.4.2.2 ! misho 12333: #if defined(SQLITE_ENABLE_SESSION)
! 12334: static void session_close_all(ShellState *p){
! 12335: int i;
! 12336: for(i=0; i<p->nSession; i++){
! 12337: session_close(&p->aSession[i]);
! 12338: }
! 12339: p->nSession = 0;
! 12340: }
! 12341: #else
! 12342: # define session_close_all(X)
! 12343: #endif
! 12344:
! 12345: /*
! 12346: ** Implementation of the xFilter function for an open session. Omit
! 12347: ** any tables named by ".session filter" but let all other table through.
! 12348: */
! 12349: #if defined(SQLITE_ENABLE_SESSION)
! 12350: static int session_filter(void *pCtx, const char *zTab){
! 12351: OpenSession *pSession = (OpenSession*)pCtx;
! 12352: int i;
! 12353: for(i=0; i<pSession->nFilter; i++){
! 12354: if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
1.4 misho 12355: }
1.4.2.2 ! misho 12356: return 1;
1.4 misho 12357: }
12358: #endif
12359:
1.4.2.1 misho 12360: /*
1.4.2.2 ! misho 12361: ** Try to deduce the type of file for zName based on its content. Return
! 12362: ** one of the SHELL_OPEN_* constants.
! 12363: **
! 12364: ** If the file does not exist or is empty but its name looks like a ZIP
! 12365: ** archive and the dfltZip flag is true, then assume it is a ZIP archive.
! 12366: ** Otherwise, assume an ordinary database regardless of the filename if
! 12367: ** the type cannot be determined from content.
! 12368: */
! 12369: int deduceDatabaseType(const char *zName, int dfltZip){
! 12370: FILE *f = fopen(zName, "rb");
! 12371: size_t n;
! 12372: int rc = SHELL_OPEN_UNSPEC;
! 12373: char zBuf[100];
! 12374: if( f==0 ){
! 12375: if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
! 12376: return SHELL_OPEN_ZIPFILE;
! 12377: }else{
! 12378: return SHELL_OPEN_NORMAL;
! 12379: }
1.4.2.1 misho 12380: }
1.4.2.2 ! misho 12381: n = fread(zBuf, 16, 1, f);
! 12382: if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
! 12383: fclose(f);
! 12384: return SHELL_OPEN_NORMAL;
! 12385: }
! 12386: fseek(f, -25, SEEK_END);
! 12387: n = fread(zBuf, 25, 1, f);
! 12388: if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
! 12389: rc = SHELL_OPEN_APPENDVFS;
1.4.2.1 misho 12390: }else{
1.4.2.2 ! misho 12391: fseek(f, -22, SEEK_END);
! 12392: n = fread(zBuf, 22, 1, f);
! 12393: if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
! 12394: && zBuf[3]==0x06 ){
! 12395: rc = SHELL_OPEN_ZIPFILE;
! 12396: }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
! 12397: rc = SHELL_OPEN_ZIPFILE;
! 12398: }
1.4.2.1 misho 12399: }
1.4.2.2 ! misho 12400: fclose(f);
! 12401: return rc;
1.4.2.1 misho 12402: }
1.4 misho 12403:
1.4.2.2 ! misho 12404: #ifdef SQLITE_ENABLE_DESERIALIZE
1.2 misho 12405: /*
1.4.2.2 ! misho 12406: ** Reconstruct an in-memory database using the output from the "dbtotxt"
! 12407: ** program. Read content from the file in p->zDbFilename. If p->zDbFilename
! 12408: ** is 0, then read from standard input.
1.2 misho 12409: */
1.4.2.2 ! misho 12410: static unsigned char *readHexDb(ShellState *p, int *pnData){
! 12411: unsigned char *a = 0;
! 12412: int nLine;
! 12413: int n = 0;
! 12414: int pgsz = 0;
! 12415: int iOffset = 0;
! 12416: int j, k;
! 12417: int rc;
! 12418: FILE *in;
! 12419: unsigned int x[16];
! 12420: char zLine[1000];
! 12421: if( p->zDbFilename ){
! 12422: in = fopen(p->zDbFilename, "r");
! 12423: if( in==0 ){
! 12424: utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
! 12425: return 0;
! 12426: }
! 12427: nLine = 0;
! 12428: }else{
! 12429: in = p->in;
! 12430: nLine = p->lineno;
! 12431: if( in==0 ) in = stdin;
! 12432: }
! 12433: *pnData = 0;
! 12434: nLine++;
! 12435: if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
! 12436: rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
! 12437: if( rc!=2 ) goto readHexDb_error;
! 12438: if( n<0 ) goto readHexDb_error;
! 12439: a = sqlite3_malloc( n ? n : 1 );
! 12440: if( a==0 ){
! 12441: utf8_printf(stderr, "Out of memory!\n");
! 12442: goto readHexDb_error;
! 12443: }
! 12444: memset(a, 0, n);
! 12445: if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
! 12446: utf8_printf(stderr, "invalid pagesize\n");
! 12447: goto readHexDb_error;
! 12448: }
! 12449: for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
! 12450: rc = sscanf(zLine, "| page %d offset %d", &j, &k);
! 12451: if( rc==2 ){
! 12452: iOffset = k;
! 12453: continue;
! 12454: }
! 12455: if( strncmp(zLine, "| end ", 6)==0 ){
! 12456: break;
! 12457: }
! 12458: rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
! 12459: &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
! 12460: &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
! 12461: if( rc==17 ){
! 12462: k = iOffset+j;
! 12463: if( k+16<=n ){
! 12464: int ii;
! 12465: for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
! 12466: }
1.4 misho 12467: }
1.2 misho 12468: }
1.4.2.2 ! misho 12469: *pnData = n;
! 12470: if( in!=p->in ){
! 12471: fclose(in);
! 12472: }else{
! 12473: p->lineno = nLine;
1.2 misho 12474: }
1.4.2.2 ! misho 12475: return a;
1.2 misho 12476:
1.4.2.2 ! misho 12477: readHexDb_error:
! 12478: if( in!=p->in ){
! 12479: fclose(in);
! 12480: }else{
! 12481: while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
! 12482: nLine++;
! 12483: if(strncmp(zLine, "| end ", 6)==0 ) break;
! 12484: }
! 12485: p->lineno = nLine;
! 12486: }
! 12487: sqlite3_free(a);
! 12488: utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
1.2 misho 12489: return 0;
12490: }
1.4.2.2 ! misho 12491: #endif /* SQLITE_ENABLE_DESERIALIZE */
1.2 misho 12492:
12493: /*
1.4.2.2 ! misho 12494: ** Scalar function "shell_int32". The first argument to this function
! 12495: ** must be a blob. The second a non-negative integer. This function
! 12496: ** reads and returns a 32-bit big-endian integer from byte
! 12497: ** offset (4*<arg2>) of the blob.
1.2 misho 12498: */
1.4.2.2 ! misho 12499: static void shellInt32(
! 12500: sqlite3_context *context,
! 12501: int argc,
! 12502: sqlite3_value **argv
1.2 misho 12503: ){
1.4.2.2 ! misho 12504: const unsigned char *pBlob;
! 12505: int nBlob;
! 12506: int iInt;
1.2 misho 12507:
1.4.2.2 ! misho 12508: UNUSED_PARAMETER(argc);
! 12509: nBlob = sqlite3_value_bytes(argv[0]);
! 12510: pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
! 12511: iInt = sqlite3_value_int(argv[1]);
! 12512:
! 12513: if( iInt>=0 && (iInt+1)*4<=nBlob ){
! 12514: const unsigned char *a = &pBlob[iInt*4];
! 12515: sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
! 12516: + ((sqlite3_int64)a[1]<<16)
! 12517: + ((sqlite3_int64)a[2]<< 8)
! 12518: + ((sqlite3_int64)a[3]<< 0);
! 12519: sqlite3_result_int64(context, iVal);
1.4 misho 12520: }
12521: }
1.2 misho 12522:
1.4 misho 12523: /*
1.4.2.2 ! misho 12524: ** Scalar function "shell_escape_crnl" used by the .recover command.
! 12525: ** The argument passed to this function is the output of built-in
! 12526: ** function quote(). If the first character of the input is "'",
! 12527: ** indicating that the value passed to quote() was a text value,
! 12528: ** then this function searches the input for "\n" and "\r" characters
! 12529: ** and adds a wrapper similar to the following:
1.4 misho 12530: **
1.4.2.2 ! misho 12531: ** replace(replace(<input>, '\n', char(10), '\r', char(13));
1.4 misho 12532: **
1.4.2.2 ! misho 12533: ** Or, if the first character of the input is not "'", then a copy
! 12534: ** of the input is returned.
1.4 misho 12535: */
1.4.2.2 ! misho 12536: static void shellEscapeCrnl(
! 12537: sqlite3_context *context,
! 12538: int argc,
! 12539: sqlite3_value **argv
! 12540: ){
! 12541: const char *zText = (const char*)sqlite3_value_text(argv[0]);
! 12542: UNUSED_PARAMETER(argc);
! 12543: if( zText[0]=='\'' ){
! 12544: int nText = sqlite3_value_bytes(argv[0]);
1.4 misho 12545: int i;
1.4.2.2 ! misho 12546: char zBuf1[20];
! 12547: char zBuf2[20];
! 12548: const char *zNL = 0;
! 12549: const char *zCR = 0;
! 12550: int nCR = 0;
! 12551: int nNL = 0;
1.2 misho 12552:
1.4.2.2 ! misho 12553: for(i=0; zText[i]; i++){
! 12554: if( zNL==0 && zText[i]=='\n' ){
! 12555: zNL = unused_string(zText, "\\n", "\\012", zBuf1);
! 12556: nNL = (int)strlen(zNL);
! 12557: }
! 12558: if( zCR==0 && zText[i]=='\r' ){
! 12559: zCR = unused_string(zText, "\\r", "\\015", zBuf2);
! 12560: nCR = (int)strlen(zCR);
! 12561: }
! 12562: }
1.4 misho 12563:
1.4.2.2 ! misho 12564: if( zNL || zCR ){
! 12565: int iOut = 0;
! 12566: i64 nMax = (nNL > nCR) ? nNL : nCR;
! 12567: i64 nAlloc = nMax * nText + (nMax+64)*2;
! 12568: char *zOut = (char*)sqlite3_malloc64(nAlloc);
! 12569: if( zOut==0 ){
! 12570: sqlite3_result_error_nomem(context);
! 12571: return;
! 12572: }
! 12573:
! 12574: if( zNL && zCR ){
! 12575: memcpy(&zOut[iOut], "replace(replace(", 16);
! 12576: iOut += 16;
! 12577: }else{
! 12578: memcpy(&zOut[iOut], "replace(", 8);
! 12579: iOut += 8;
! 12580: }
! 12581: for(i=0; zText[i]; i++){
! 12582: if( zText[i]=='\n' ){
! 12583: memcpy(&zOut[iOut], zNL, nNL);
! 12584: iOut += nNL;
! 12585: }else if( zText[i]=='\r' ){
! 12586: memcpy(&zOut[iOut], zCR, nCR);
! 12587: iOut += nCR;
! 12588: }else{
! 12589: zOut[iOut] = zText[i];
! 12590: iOut++;
1.2 misho 12591: }
12592: }
1.4 misho 12593:
1.4.2.2 ! misho 12594: if( zNL ){
! 12595: memcpy(&zOut[iOut], ",'", 2); iOut += 2;
! 12596: memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
! 12597: memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
! 12598: }
! 12599: if( zCR ){
! 12600: memcpy(&zOut[iOut], ",'", 2); iOut += 2;
! 12601: memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
! 12602: memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
! 12603: }
! 12604:
! 12605: sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
! 12606: sqlite3_free(zOut);
! 12607: return;
1.4 misho 12608: }
12609: }
12610:
1.4.2.2 ! misho 12611: sqlite3_result_value(context, argv[0]);
1.4 misho 12612: }
12613:
1.4.2.2 ! misho 12614: /* Flags for open_db().
! 12615: **
! 12616: ** The default behavior of open_db() is to exit(1) if the database fails to
! 12617: ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
! 12618: ** but still returns without calling exit.
! 12619: **
! 12620: ** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
! 12621: ** ZIP archive if the file does not exist or is empty and its name matches
! 12622: ** the *.zip pattern.
1.4 misho 12623: */
1.4.2.2 ! misho 12624: #define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
! 12625: #define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
1.4 misho 12626:
12627: /*
1.4.2.2 ! misho 12628: ** Make sure the database is open. If it is not, then open it. If
! 12629: ** the database fails to open, print an error message and exit.
1.4 misho 12630: */
1.4.2.2 ! misho 12631: static void open_db(ShellState *p, int openFlags){
! 12632: if( p->db==0 ){
! 12633: if( p->openMode==SHELL_OPEN_UNSPEC ){
! 12634: if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
! 12635: p->openMode = SHELL_OPEN_NORMAL;
! 12636: }else{
! 12637: p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
! 12638: (openFlags & OPEN_DB_ZIPFILE)!=0);
! 12639: }
! 12640: }
! 12641: switch( p->openMode ){
! 12642: case SHELL_OPEN_APPENDVFS: {
! 12643: sqlite3_open_v2(p->zDbFilename, &p->db,
! 12644: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
! 12645: break;
! 12646: }
! 12647: case SHELL_OPEN_HEXDB:
! 12648: case SHELL_OPEN_DESERIALIZE: {
! 12649: sqlite3_open(0, &p->db);
! 12650: break;
! 12651: }
! 12652: case SHELL_OPEN_ZIPFILE: {
! 12653: sqlite3_open(":memory:", &p->db);
! 12654: break;
! 12655: }
! 12656: case SHELL_OPEN_READONLY: {
! 12657: sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
! 12658: break;
! 12659: }
! 12660: case SHELL_OPEN_UNSPEC:
! 12661: case SHELL_OPEN_NORMAL: {
! 12662: sqlite3_open(p->zDbFilename, &p->db);
! 12663: break;
! 12664: }
! 12665: }
! 12666: globalDb = p->db;
! 12667: if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
! 12668: utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
! 12669: p->zDbFilename, sqlite3_errmsg(p->db));
! 12670: if( openFlags & OPEN_DB_KEEPALIVE ){
! 12671: sqlite3_open(":memory:", &p->db);
! 12672: return;
! 12673: }
! 12674: exit(1);
! 12675: }
! 12676: #ifndef SQLITE_OMIT_LOAD_EXTENSION
! 12677: sqlite3_enable_load_extension(p->db, 1);
1.4 misho 12678: #endif
1.4.2.2 ! misho 12679: sqlite3_fileio_init(p->db, 0, 0);
! 12680: sqlite3_shathree_init(p->db, 0, 0);
! 12681: sqlite3_completion_init(p->db, 0, 0);
! 12682: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 12683: sqlite3_dbdata_init(p->db, 0, 0);
! 12684: #endif
! 12685: #ifdef SQLITE_HAVE_ZLIB
! 12686: sqlite3_zipfile_init(p->db, 0, 0);
! 12687: sqlite3_sqlar_init(p->db, 0, 0);
! 12688: #endif
! 12689: sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
! 12690: shellAddSchemaName, 0, 0);
! 12691: sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
! 12692: shellModuleSchema, 0, 0);
! 12693: sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
! 12694: shellPutsFunc, 0, 0);
! 12695: sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
! 12696: shellEscapeCrnl, 0, 0);
! 12697: sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
! 12698: shellInt32, 0, 0);
! 12699: #ifndef SQLITE_NOHAVE_SYSTEM
! 12700: sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
! 12701: editFunc, 0, 0);
! 12702: sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
! 12703: editFunc, 0, 0);
! 12704: #endif
! 12705: if( p->openMode==SHELL_OPEN_ZIPFILE ){
! 12706: char *zSql = sqlite3_mprintf(
! 12707: "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
! 12708: sqlite3_exec(p->db, zSql, 0, 0, 0);
! 12709: sqlite3_free(zSql);
! 12710: }
! 12711: #ifdef SQLITE_ENABLE_DESERIALIZE
! 12712: else
! 12713: if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
! 12714: int rc;
! 12715: int nData = 0;
! 12716: unsigned char *aData;
! 12717: if( p->openMode==SHELL_OPEN_DESERIALIZE ){
! 12718: aData = (unsigned char*)readFile(p->zDbFilename, &nData);
! 12719: }else{
! 12720: aData = readHexDb(p, &nData);
! 12721: if( aData==0 ){
! 12722: return;
! 12723: }
! 12724: }
! 12725: rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
! 12726: SQLITE_DESERIALIZE_RESIZEABLE |
! 12727: SQLITE_DESERIALIZE_FREEONCLOSE);
! 12728: if( rc ){
! 12729: utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
! 12730: }
! 12731: if( p->szMax>0 ){
! 12732: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
! 12733: }
! 12734: }
1.4 misho 12735: #endif
1.4.2.2 ! misho 12736: }
1.4 misho 12737: }
1.4.2.2 ! misho 12738:
! 12739: /*
! 12740: ** Attempt to close the databaes connection. Report errors.
! 12741: */
! 12742: void close_db(sqlite3 *db){
! 12743: int rc = sqlite3_close(db);
! 12744: if( rc ){
! 12745: utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
! 12746: rc, sqlite3_errmsg(db));
! 12747: }
1.4 misho 12748: }
12749:
1.4.2.2 ! misho 12750: #if HAVE_READLINE || HAVE_EDITLINE
1.4 misho 12751: /*
1.4.2.2 ! misho 12752: ** Readline completion callbacks
1.4 misho 12753: */
1.4.2.2 ! misho 12754: static char *readline_completion_generator(const char *text, int state){
! 12755: static sqlite3_stmt *pStmt = 0;
! 12756: char *zRet;
! 12757: if( state==0 ){
! 12758: char *zSql;
! 12759: sqlite3_finalize(pStmt);
! 12760: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
! 12761: " FROM completion(%Q) ORDER BY 1", text);
! 12762: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
! 12763: sqlite3_free(zSql);
! 12764: }
! 12765: if( sqlite3_step(pStmt)==SQLITE_ROW ){
! 12766: zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
! 12767: }else{
! 12768: sqlite3_finalize(pStmt);
! 12769: pStmt = 0;
! 12770: zRet = 0;
! 12771: }
! 12772: return zRet;
! 12773: }
! 12774: static char **readline_completion(const char *zText, int iStart, int iEnd){
! 12775: rl_attempted_completion_over = 1;
! 12776: return rl_completion_matches(zText, readline_completion_generator);
! 12777: }
1.4 misho 12778:
1.4.2.2 ! misho 12779: #elif HAVE_LINENOISE
! 12780: /*
! 12781: ** Linenoise completion callback
! 12782: */
! 12783: static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
! 12784: int nLine = strlen30(zLine);
! 12785: int i, iStart;
! 12786: sqlite3_stmt *pStmt = 0;
! 12787: char *zSql;
! 12788: char zBuf[1000];
1.4 misho 12789:
1.4.2.2 ! misho 12790: if( nLine>sizeof(zBuf)-30 ) return;
! 12791: if( zLine[0]=='.' || zLine[0]=='#') return;
! 12792: for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
! 12793: if( i==nLine-1 ) return;
! 12794: iStart = i+1;
! 12795: memcpy(zBuf, zLine, iStart);
! 12796: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
! 12797: " FROM completion(%Q,%Q) ORDER BY 1",
! 12798: &zLine[iStart], zLine);
! 12799: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
! 12800: sqlite3_free(zSql);
! 12801: sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
! 12802: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 12803: const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
! 12804: int nCompletion = sqlite3_column_bytes(pStmt, 0);
! 12805: if( iStart+nCompletion < sizeof(zBuf)-1 ){
! 12806: memcpy(zBuf+iStart, zCompletion, nCompletion+1);
! 12807: linenoiseAddCompletion(lc, zBuf);
1.4 misho 12808: }
12809: }
1.4.2.2 ! misho 12810: sqlite3_finalize(pStmt);
1.4 misho 12811: }
1.4.2.2 ! misho 12812: #endif
1.4 misho 12813:
12814: /*
1.4.2.2 ! misho 12815: ** Do C-language style dequoting.
1.4 misho 12816: **
1.4.2.2 ! misho 12817: ** \a -> alarm
! 12818: ** \b -> backspace
! 12819: ** \t -> tab
! 12820: ** \n -> newline
! 12821: ** \v -> vertical tab
! 12822: ** \f -> form feed
! 12823: ** \r -> carriage return
! 12824: ** \s -> space
! 12825: ** \" -> "
! 12826: ** \' -> '
! 12827: ** \\ -> backslash
! 12828: ** \NNN -> ascii character NNN in octal
1.4 misho 12829: */
1.4.2.2 ! misho 12830: static void resolve_backslashes(char *z){
! 12831: int i, j;
! 12832: char c;
! 12833: while( *z && *z!='\\' ) z++;
! 12834: for(i=j=0; (c = z[i])!=0; i++, j++){
! 12835: if( c=='\\' && z[i+1]!=0 ){
! 12836: c = z[++i];
! 12837: if( c=='a' ){
! 12838: c = '\a';
! 12839: }else if( c=='b' ){
! 12840: c = '\b';
! 12841: }else if( c=='t' ){
! 12842: c = '\t';
! 12843: }else if( c=='n' ){
! 12844: c = '\n';
! 12845: }else if( c=='v' ){
! 12846: c = '\v';
! 12847: }else if( c=='f' ){
! 12848: c = '\f';
! 12849: }else if( c=='r' ){
! 12850: c = '\r';
! 12851: }else if( c=='"' ){
! 12852: c = '"';
! 12853: }else if( c=='\'' ){
! 12854: c = '\'';
! 12855: }else if( c=='\\' ){
! 12856: c = '\\';
! 12857: }else if( c>='0' && c<='7' ){
! 12858: c -= '0';
! 12859: if( z[i+1]>='0' && z[i+1]<='7' ){
! 12860: i++;
! 12861: c = (c<<3) + z[i] - '0';
! 12862: if( z[i+1]>='0' && z[i+1]<='7' ){
! 12863: i++;
! 12864: c = (c<<3) + z[i] - '0';
1.4 misho 12865: }
12866: }
12867: }
1.4.2.2 ! misho 12868: }
! 12869: z[j] = c;
! 12870: }
! 12871: if( j<i ) z[j] = 0;
! 12872: }
1.4 misho 12873:
1.4.2.2 ! misho 12874: /*
! 12875: ** Interpret zArg as either an integer or a boolean value. Return 1 or 0
! 12876: ** for TRUE and FALSE. Return the integer value if appropriate.
! 12877: */
! 12878: static int booleanValue(const char *zArg){
! 12879: int i;
! 12880: if( zArg[0]=='0' && zArg[1]=='x' ){
! 12881: for(i=2; hexDigitValue(zArg[i])>=0; i++){}
! 12882: }else{
! 12883: for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
! 12884: }
! 12885: if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
! 12886: if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
! 12887: return 1;
! 12888: }
! 12889: if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
! 12890: return 0;
! 12891: }
! 12892: utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
! 12893: zArg);
! 12894: return 0;
! 12895: }
1.4 misho 12896:
1.4.2.2 ! misho 12897: /*
! 12898: ** Set or clear a shell flag according to a boolean value.
! 12899: */
! 12900: static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
! 12901: if( booleanValue(zArg) ){
! 12902: ShellSetFlag(p, mFlag);
! 12903: }else{
! 12904: ShellClearFlag(p, mFlag);
! 12905: }
! 12906: }
1.4 misho 12907:
1.4.2.2 ! misho 12908: /*
! 12909: ** Close an output file, assuming it is not stderr or stdout
! 12910: */
! 12911: static void output_file_close(FILE *f){
! 12912: if( f && f!=stdout && f!=stderr ) fclose(f);
! 12913: }
1.2 misho 12914:
1.4.2.2 ! misho 12915: /*
! 12916: ** Try to open an output file. The names "stdout" and "stderr" are
! 12917: ** recognized and do the right thing. NULL is returned if the output
! 12918: ** filename is "off".
! 12919: */
! 12920: static FILE *output_file_open(const char *zFile, int bTextMode){
! 12921: FILE *f;
! 12922: if( strcmp(zFile,"stdout")==0 ){
! 12923: f = stdout;
! 12924: }else if( strcmp(zFile, "stderr")==0 ){
! 12925: f = stderr;
! 12926: }else if( strcmp(zFile, "off")==0 ){
! 12927: f = 0;
! 12928: }else{
! 12929: f = fopen(zFile, bTextMode ? "w" : "wb");
! 12930: if( f==0 ){
! 12931: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
! 12932: }
! 12933: }
! 12934: return f;
! 12935: }
1.2 misho 12936:
1.4.2.2 ! misho 12937: #ifndef SQLITE_OMIT_TRACE
! 12938: /*
! 12939: ** A routine for handling output from sqlite3_trace().
! 12940: */
! 12941: static int sql_trace_callback(
! 12942: unsigned mType, /* The trace type */
! 12943: void *pArg, /* The ShellState pointer */
! 12944: void *pP, /* Usually a pointer to sqlite_stmt */
! 12945: void *pX /* Auxiliary output */
! 12946: ){
! 12947: ShellState *p = (ShellState*)pArg;
! 12948: sqlite3_stmt *pStmt;
! 12949: const char *zSql;
! 12950: int nSql;
! 12951: if( p->traceOut==0 ) return 0;
! 12952: if( mType==SQLITE_TRACE_CLOSE ){
! 12953: utf8_printf(p->traceOut, "-- closing database connection\n");
! 12954: return 0;
! 12955: }
! 12956: if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
! 12957: zSql = (const char*)pX;
! 12958: }else{
! 12959: pStmt = (sqlite3_stmt*)pP;
! 12960: switch( p->eTraceType ){
! 12961: case SHELL_TRACE_EXPANDED: {
! 12962: zSql = sqlite3_expanded_sql(pStmt);
! 12963: break;
1.4 misho 12964: }
1.4.2.2 ! misho 12965: #ifdef SQLITE_ENABLE_NORMALIZE
! 12966: case SHELL_TRACE_NORMALIZED: {
! 12967: zSql = sqlite3_normalized_sql(pStmt);
! 12968: break;
1.2 misho 12969: }
1.4.2.2 ! misho 12970: #endif
! 12971: default: {
! 12972: zSql = sqlite3_sql(pStmt);
! 12973: break;
1.2 misho 12974: }
12975: }
1.4.2.2 ! misho 12976: }
! 12977: if( zSql==0 ) return 0;
! 12978: nSql = strlen30(zSql);
! 12979: while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
! 12980: switch( mType ){
! 12981: case SQLITE_TRACE_ROW:
! 12982: case SQLITE_TRACE_STMT: {
! 12983: utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
! 12984: break;
! 12985: }
! 12986: case SQLITE_TRACE_PROFILE: {
! 12987: sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
! 12988: utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
! 12989: break;
! 12990: }
! 12991: }
! 12992: return 0;
1.2 misho 12993: }
1.4.2.2 ! misho 12994: #endif
1.2 misho 12995:
1.4.2.1 misho 12996: /*
1.4.2.2 ! misho 12997: ** A no-op routine that runs with the ".breakpoint" doc-command. This is
! 12998: ** a useful spot to set a debugger breakpoint.
1.4.2.1 misho 12999: */
1.4.2.2 ! misho 13000: static void test_breakpoint(void){
! 13001: static int nCall = 0;
! 13002: nCall++;
1.4.2.1 misho 13003: }
13004:
13005: /*
1.4.2.2 ! misho 13006: ** An object used to read a CSV and other files for import.
1.4.2.1 misho 13007: */
1.4.2.2 ! misho 13008: typedef struct ImportCtx ImportCtx;
! 13009: struct ImportCtx {
! 13010: const char *zFile; /* Name of the input file */
! 13011: FILE *in; /* Read the CSV text from this input stream */
! 13012: char *z; /* Accumulated text for a field */
! 13013: int n; /* Number of bytes in z */
! 13014: int nAlloc; /* Space allocated for z[] */
! 13015: int nLine; /* Current line number */
! 13016: int bNotFirst; /* True if one or more bytes already read */
! 13017: int cTerm; /* Character that terminated the most recent field */
! 13018: int cColSep; /* The column separator character. (Usually ",") */
! 13019: int cRowSep; /* The row separator character. (Usually "\n") */
! 13020: };
1.4.2.1 misho 13021:
1.4.2.2 ! misho 13022: /* Append a single byte to z[] */
! 13023: static void import_append_char(ImportCtx *p, int c){
! 13024: if( p->n+1>=p->nAlloc ){
! 13025: p->nAlloc += p->nAlloc + 100;
! 13026: p->z = sqlite3_realloc64(p->z, p->nAlloc);
! 13027: if( p->z==0 ) shell_out_of_memory();
1.4.2.1 misho 13028: }
1.4.2.2 ! misho 13029: p->z[p->n++] = (char)c;
! 13030: }
1.4.2.1 misho 13031:
1.4.2.2 ! misho 13032: /* Read a single field of CSV text. Compatible with rfc4180 and extended
! 13033: ** with the option of having a separator other than ",".
! 13034: **
! 13035: ** + Input comes from p->in.
! 13036: ** + Store results in p->z of length p->n. Space to hold p->z comes
! 13037: ** from sqlite3_malloc64().
! 13038: ** + Use p->cSep as the column separator. The default is ",".
! 13039: ** + Use p->rSep as the row separator. The default is "\n".
! 13040: ** + Keep track of the line number in p->nLine.
! 13041: ** + Store the character that terminates the field in p->cTerm. Store
! 13042: ** EOF on end-of-file.
! 13043: ** + Report syntax errors on stderr
! 13044: */
! 13045: static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
! 13046: int c;
! 13047: int cSep = p->cColSep;
! 13048: int rSep = p->cRowSep;
! 13049: p->n = 0;
! 13050: c = fgetc(p->in);
! 13051: if( c==EOF || seenInterrupt ){
! 13052: p->cTerm = EOF;
! 13053: return 0;
! 13054: }
! 13055: if( c=='"' ){
! 13056: int pc, ppc;
! 13057: int startLine = p->nLine;
! 13058: int cQuote = c;
! 13059: pc = ppc = 0;
! 13060: while( 1 ){
! 13061: c = fgetc(p->in);
! 13062: if( c==rSep ) p->nLine++;
! 13063: if( c==cQuote ){
! 13064: if( pc==cQuote ){
! 13065: pc = 0;
! 13066: continue;
! 13067: }
1.4.2.1 misho 13068: }
1.4.2.2 ! misho 13069: if( (c==cSep && pc==cQuote)
! 13070: || (c==rSep && pc==cQuote)
! 13071: || (c==rSep && pc=='\r' && ppc==cQuote)
! 13072: || (c==EOF && pc==cQuote)
! 13073: ){
! 13074: do{ p->n--; }while( p->z[p->n]!=cQuote );
! 13075: p->cTerm = c;
! 13076: break;
! 13077: }
! 13078: if( pc==cQuote && c!='\r' ){
! 13079: utf8_printf(stderr, "%s:%d: unescaped %c character\n",
! 13080: p->zFile, p->nLine, cQuote);
! 13081: }
! 13082: if( c==EOF ){
! 13083: utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
! 13084: p->zFile, startLine, cQuote);
! 13085: p->cTerm = c;
1.4.2.1 misho 13086: break;
13087: }
1.4.2.2 ! misho 13088: import_append_char(p, c);
! 13089: ppc = pc;
! 13090: pc = c;
! 13091: }
! 13092: }else{
! 13093: /* If this is the first field being parsed and it begins with the
! 13094: ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
! 13095: if( (c&0xff)==0xef && p->bNotFirst==0 ){
! 13096: import_append_char(p, c);
! 13097: c = fgetc(p->in);
! 13098: if( (c&0xff)==0xbb ){
! 13099: import_append_char(p, c);
! 13100: c = fgetc(p->in);
! 13101: if( (c&0xff)==0xbf ){
! 13102: p->bNotFirst = 1;
! 13103: p->n = 0;
! 13104: return csv_read_one_field(p);
! 13105: }
! 13106: }
! 13107: }
! 13108: while( c!=EOF && c!=cSep && c!=rSep ){
! 13109: import_append_char(p, c);
! 13110: c = fgetc(p->in);
! 13111: }
! 13112: if( c==rSep ){
! 13113: p->nLine++;
! 13114: if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
1.4.2.1 misho 13115: }
1.4.2.2 ! misho 13116: p->cTerm = c;
1.4.2.1 misho 13117: }
1.4.2.2 ! misho 13118: if( p->z ) p->z[p->n] = 0;
! 13119: p->bNotFirst = 1;
! 13120: return p->z;
1.4.2.1 misho 13121: }
13122:
1.4.2.2 ! misho 13123: /* Read a single field of ASCII delimited text.
! 13124: **
! 13125: ** + Input comes from p->in.
! 13126: ** + Store results in p->z of length p->n. Space to hold p->z comes
! 13127: ** from sqlite3_malloc64().
! 13128: ** + Use p->cSep as the column separator. The default is "\x1F".
! 13129: ** + Use p->rSep as the row separator. The default is "\x1E".
! 13130: ** + Keep track of the row number in p->nLine.
! 13131: ** + Store the character that terminates the field in p->cTerm. Store
! 13132: ** EOF on end-of-file.
! 13133: ** + Report syntax errors on stderr
1.4.2.1 misho 13134: */
1.4.2.2 ! misho 13135: static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
! 13136: int c;
! 13137: int cSep = p->cColSep;
! 13138: int rSep = p->cRowSep;
! 13139: p->n = 0;
! 13140: c = fgetc(p->in);
! 13141: if( c==EOF || seenInterrupt ){
! 13142: p->cTerm = EOF;
! 13143: return 0;
1.4.2.1 misho 13144: }
1.4.2.2 ! misho 13145: while( c!=EOF && c!=cSep && c!=rSep ){
! 13146: import_append_char(p, c);
! 13147: c = fgetc(p->in);
! 13148: }
! 13149: if( c==rSep ){
! 13150: p->nLine++;
! 13151: }
! 13152: p->cTerm = c;
! 13153: if( p->z ) p->z[p->n] = 0;
! 13154: return p->z;
1.4.2.1 misho 13155: }
1.2 misho 13156:
13157: /*
1.4.2.2 ! misho 13158: ** Try to transfer data for table zTable. If an error is seen while
! 13159: ** moving forward, try to go backwards. The backwards movement won't
! 13160: ** work for WITHOUT ROWID tables.
1.2 misho 13161: */
1.4.2.2 ! misho 13162: static void tryToCloneData(
! 13163: ShellState *p,
! 13164: sqlite3 *newDb,
! 13165: const char *zTable
! 13166: ){
! 13167: sqlite3_stmt *pQuery = 0;
! 13168: sqlite3_stmt *pInsert = 0;
! 13169: char *zQuery = 0;
! 13170: char *zInsert = 0;
1.2 misho 13171: int rc;
1.4.2.2 ! misho 13172: int i, j, n;
! 13173: int nTable = strlen30(zTable);
! 13174: int k = 0;
! 13175: int cnt = 0;
! 13176: const int spinRate = 10000;
1.4 misho 13177:
1.4.2.2 ! misho 13178: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
! 13179: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
! 13180: if( rc ){
! 13181: utf8_printf(stderr, "Error %d: %s on [%s]\n",
! 13182: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
! 13183: zQuery);
! 13184: goto end_data_xfer;
1.2 misho 13185: }
1.4.2.2 ! misho 13186: n = sqlite3_column_count(pQuery);
! 13187: zInsert = sqlite3_malloc64(200 + nTable + n*3);
! 13188: if( zInsert==0 ) shell_out_of_memory();
! 13189: sqlite3_snprintf(200+nTable,zInsert,
! 13190: "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
! 13191: i = strlen30(zInsert);
! 13192: for(j=1; j<n; j++){
! 13193: memcpy(zInsert+i, ",?", 2);
! 13194: i += 2;
! 13195: }
! 13196: memcpy(zInsert+i, ");", 3);
! 13197: rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
! 13198: if( rc ){
! 13199: utf8_printf(stderr, "Error %d: %s on [%s]\n",
! 13200: sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
! 13201: zQuery);
! 13202: goto end_data_xfer;
! 13203: }
! 13204: for(k=0; k<2; k++){
! 13205: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
! 13206: for(i=0; i<n; i++){
! 13207: switch( sqlite3_column_type(pQuery, i) ){
! 13208: case SQLITE_NULL: {
! 13209: sqlite3_bind_null(pInsert, i+1);
! 13210: break;
! 13211: }
! 13212: case SQLITE_INTEGER: {
! 13213: sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
! 13214: break;
! 13215: }
! 13216: case SQLITE_FLOAT: {
! 13217: sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
! 13218: break;
! 13219: }
! 13220: case SQLITE_TEXT: {
! 13221: sqlite3_bind_text(pInsert, i+1,
! 13222: (const char*)sqlite3_column_text(pQuery,i),
! 13223: -1, SQLITE_STATIC);
! 13224: break;
! 13225: }
! 13226: case SQLITE_BLOB: {
! 13227: sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
! 13228: sqlite3_column_bytes(pQuery,i),
! 13229: SQLITE_STATIC);
! 13230: break;
! 13231: }
! 13232: }
! 13233: } /* End for */
! 13234: rc = sqlite3_step(pInsert);
! 13235: if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
! 13236: utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
! 13237: sqlite3_errmsg(newDb));
1.4.2.1 misho 13238: }
1.4.2.2 ! misho 13239: sqlite3_reset(pInsert);
! 13240: cnt++;
! 13241: if( (cnt%spinRate)==0 ){
! 13242: printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
! 13243: fflush(stdout);
1.4.2.1 misho 13244: }
1.4.2.2 ! misho 13245: } /* End while */
! 13246: if( rc==SQLITE_DONE ) break;
! 13247: sqlite3_finalize(pQuery);
! 13248: sqlite3_free(zQuery);
! 13249: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
! 13250: zTable);
! 13251: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
! 13252: if( rc ){
! 13253: utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
! 13254: break;
1.4.2.1 misho 13255: }
1.4.2.2 ! misho 13256: } /* End for(k=0...) */
1.4.2.1 misho 13257:
1.4.2.2 ! misho 13258: end_data_xfer:
! 13259: sqlite3_finalize(pQuery);
! 13260: sqlite3_finalize(pInsert);
! 13261: sqlite3_free(zQuery);
! 13262: sqlite3_free(zInsert);
1.2 misho 13263: }
13264:
1.4.2.2 ! misho 13265:
1.2 misho 13266: /*
1.4.2.2 ! misho 13267: ** Try to transfer all rows of the schema that match zWhere. For
! 13268: ** each row, invoke xForEach() on the object defined by that row.
! 13269: ** If an error is encountered while moving forward through the
! 13270: ** sqlite_master table, try again moving backwards.
1.2 misho 13271: */
1.4.2.2 ! misho 13272: static void tryToCloneSchema(
1.4 misho 13273: ShellState *p,
1.4.2.2 ! misho 13274: sqlite3 *newDb,
! 13275: const char *zWhere,
! 13276: void (*xForEach)(ShellState*,sqlite3*,const char*)
1.2 misho 13277: ){
1.4.2.2 ! misho 13278: sqlite3_stmt *pQuery = 0;
! 13279: char *zQuery = 0;
1.2 misho 13280: int rc;
1.4.2.2 ! misho 13281: const unsigned char *zName;
! 13282: const unsigned char *zSql;
! 13283: char *zErrMsg = 0;
! 13284:
! 13285: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
! 13286: " WHERE %s", zWhere);
! 13287: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
! 13288: if( rc ){
! 13289: utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
! 13290: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
! 13291: zQuery);
! 13292: goto end_schema_xfer;
! 13293: }
! 13294: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
! 13295: zName = sqlite3_column_text(pQuery, 0);
! 13296: zSql = sqlite3_column_text(pQuery, 1);
! 13297: printf("%s... ", zName); fflush(stdout);
! 13298: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
! 13299: if( zErrMsg ){
! 13300: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
! 13301: sqlite3_free(zErrMsg);
! 13302: zErrMsg = 0;
1.2 misho 13303: }
1.4.2.2 ! misho 13304: if( xForEach ){
! 13305: xForEach(p, newDb, (const char*)zName);
! 13306: }
! 13307: printf("done\n");
! 13308: }
! 13309: if( rc!=SQLITE_DONE ){
! 13310: sqlite3_finalize(pQuery);
! 13311: sqlite3_free(zQuery);
! 13312: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
! 13313: " WHERE %s ORDER BY rowid DESC", zWhere);
! 13314: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
1.2 misho 13315: if( rc ){
1.4.2.2 ! misho 13316: utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
! 13317: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
! 13318: zQuery);
! 13319: goto end_schema_xfer;
! 13320: }
! 13321: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
! 13322: zName = sqlite3_column_text(pQuery, 0);
! 13323: zSql = sqlite3_column_text(pQuery, 1);
! 13324: printf("%s... ", zName); fflush(stdout);
! 13325: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
! 13326: if( zErrMsg ){
! 13327: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
! 13328: sqlite3_free(zErrMsg);
! 13329: zErrMsg = 0;
! 13330: }
! 13331: if( xForEach ){
! 13332: xForEach(p, newDb, (const char*)zName);
! 13333: }
! 13334: printf("done\n");
1.2 misho 13335: }
13336: }
1.4.2.2 ! misho 13337: end_schema_xfer:
! 13338: sqlite3_finalize(pQuery);
! 13339: sqlite3_free(zQuery);
1.4 misho 13340: }
1.4.2.1 misho 13341:
13342: /*
1.4.2.2 ! misho 13343: ** Open a new database file named "zNewDb". Try to recover as much information
! 13344: ** as possible out of the main database (which might be corrupt) and write it
! 13345: ** into zNewDb.
1.4.2.1 misho 13346: */
1.4.2.2 ! misho 13347: static void tryToClone(ShellState *p, const char *zNewDb){
! 13348: int rc;
! 13349: sqlite3 *newDb = 0;
! 13350: if( access(zNewDb,0)==0 ){
! 13351: utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
! 13352: return;
1.4.2.1 misho 13353: }
1.4.2.2 ! misho 13354: rc = sqlite3_open(zNewDb, &newDb);
! 13355: if( rc ){
! 13356: utf8_printf(stderr, "Cannot create output database: %s\n",
! 13357: sqlite3_errmsg(newDb));
1.4 misho 13358: }else{
1.4.2.2 ! misho 13359: sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
! 13360: sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
! 13361: tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
! 13362: tryToCloneSchema(p, newDb, "type!='table'", 0);
! 13363: sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
! 13364: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
1.4 misho 13365: }
1.4.2.2 ! misho 13366: close_db(newDb);
1.4 misho 13367: }
13368:
13369: /*
1.4.2.2 ! misho 13370: ** Change the output file back to stdout.
! 13371: **
! 13372: ** If the p->doXdgOpen flag is set, that means the output was being
! 13373: ** redirected to a temporary file named by p->zTempFile. In that case,
! 13374: ** launch start/open/xdg-open on that temporary file.
1.4 misho 13375: */
1.4.2.2 ! misho 13376: static void output_reset(ShellState *p){
! 13377: if( p->outfile[0]=='|' ){
! 13378: #ifndef SQLITE_OMIT_POPEN
! 13379: pclose(p->out);
! 13380: #endif
! 13381: }else{
! 13382: output_file_close(p->out);
! 13383: #ifndef SQLITE_NOHAVE_SYSTEM
! 13384: if( p->doXdgOpen ){
! 13385: const char *zXdgOpenCmd =
! 13386: #if defined(_WIN32)
! 13387: "start";
! 13388: #elif defined(__APPLE__)
! 13389: "open";
! 13390: #else
! 13391: "xdg-open";
! 13392: #endif
! 13393: char *zCmd;
! 13394: zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
! 13395: if( system(zCmd) ){
! 13396: utf8_printf(stderr, "Failed: [%s]\n", zCmd);
! 13397: }
! 13398: sqlite3_free(zCmd);
! 13399: outputModePop(p);
! 13400: p->doXdgOpen = 0;
! 13401: sqlite3_sleep(100);
! 13402: }
! 13403: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
1.4 misho 13404: }
1.4.2.2 ! misho 13405: p->outfile[0] = 0;
! 13406: p->out = stdout;
1.4 misho 13407: }
13408:
13409: /*
1.4.2.2 ! misho 13410: ** Run an SQL command and return the single integer result.
1.4 misho 13411: */
1.4.2.2 ! misho 13412: static int db_int(ShellState *p, const char *zSql){
! 13413: sqlite3_stmt *pStmt;
! 13414: int res = 0;
! 13415: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
! 13416: if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
! 13417: res = sqlite3_column_int(pStmt,0);
1.4 misho 13418: }
1.4.2.2 ! misho 13419: sqlite3_finalize(pStmt);
! 13420: return res;
1.4 misho 13421: }
13422:
13423: /*
1.4.2.2 ! misho 13424: ** Convert a 2-byte or 4-byte big-endian integer into a native integer
1.4 misho 13425: */
1.4.2.2 ! misho 13426: static unsigned int get2byteInt(unsigned char *a){
! 13427: return (a[0]<<8) + a[1];
! 13428: }
! 13429: static unsigned int get4byteInt(unsigned char *a){
! 13430: return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
1.4 misho 13431: }
1.2 misho 13432:
13433: /*
1.4.2.2 ! misho 13434: ** Implementation of the ".info" command.
! 13435: **
! 13436: ** Return 1 on error, 2 to exit, and 0 otherwise.
1.2 misho 13437: */
1.4.2.2 ! misho 13438: static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
! 13439: static const struct { const char *zName; int ofst; } aField[] = {
! 13440: { "file change counter:", 24 },
! 13441: { "database page count:", 28 },
! 13442: { "freelist page count:", 36 },
! 13443: { "schema cookie:", 40 },
! 13444: { "schema format:", 44 },
! 13445: { "default cache size:", 48 },
! 13446: { "autovacuum top root:", 52 },
! 13447: { "incremental vacuum:", 64 },
! 13448: { "text encoding:", 56 },
! 13449: { "user version:", 60 },
! 13450: { "application id:", 68 },
! 13451: { "software version:", 96 },
! 13452: };
! 13453: static const struct { const char *zName; const char *zSql; } aQuery[] = {
! 13454: { "number of tables:",
! 13455: "SELECT count(*) FROM %s WHERE type='table'" },
! 13456: { "number of indexes:",
! 13457: "SELECT count(*) FROM %s WHERE type='index'" },
! 13458: { "number of triggers:",
! 13459: "SELECT count(*) FROM %s WHERE type='trigger'" },
! 13460: { "number of views:",
! 13461: "SELECT count(*) FROM %s WHERE type='view'" },
! 13462: { "schema size:",
! 13463: "SELECT total(length(sql)) FROM %s" },
! 13464: };
! 13465: int i, rc;
! 13466: unsigned iDataVersion;
! 13467: char *zSchemaTab;
! 13468: char *zDb = nArg>=2 ? azArg[1] : "main";
! 13469: sqlite3_stmt *pStmt = 0;
! 13470: unsigned char aHdr[100];
! 13471: open_db(p, 0);
! 13472: if( p->db==0 ) return 1;
! 13473: rc = sqlite3_prepare_v2(p->db,
! 13474: "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
! 13475: -1, &pStmt, 0);
! 13476: if( rc ){
! 13477: if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
! 13478: utf8_printf(stderr, "the \".dbinfo\" command requires the "
! 13479: "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
! 13480: }else{
! 13481: utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 13482: }
1.4.2.2 ! misho 13483: sqlite3_finalize(pStmt);
! 13484: return 1;
! 13485: }
! 13486: sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
! 13487: if( sqlite3_step(pStmt)==SQLITE_ROW
! 13488: && sqlite3_column_bytes(pStmt,0)>100
! 13489: ){
! 13490: memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
! 13491: sqlite3_finalize(pStmt);
! 13492: }else{
! 13493: raw_printf(stderr, "unable to read database header\n");
! 13494: sqlite3_finalize(pStmt);
! 13495: return 1;
! 13496: }
! 13497: i = get2byteInt(aHdr+16);
! 13498: if( i==1 ) i = 65536;
! 13499: utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
! 13500: utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
! 13501: utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
! 13502: utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
! 13503: for(i=0; i<ArraySize(aField); i++){
! 13504: int ofst = aField[i].ofst;
! 13505: unsigned int val = get4byteInt(aHdr + ofst);
! 13506: utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
! 13507: switch( ofst ){
! 13508: case 56: {
! 13509: if( val==1 ) raw_printf(p->out, " (utf8)");
! 13510: if( val==2 ) raw_printf(p->out, " (utf16le)");
! 13511: if( val==3 ) raw_printf(p->out, " (utf16be)");
! 13512: }
! 13513: }
! 13514: raw_printf(p->out, "\n");
! 13515: }
! 13516: if( zDb==0 ){
! 13517: zSchemaTab = sqlite3_mprintf("main.sqlite_master");
! 13518: }else if( strcmp(zDb,"temp")==0 ){
! 13519: zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
! 13520: }else{
! 13521: zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
! 13522: }
! 13523: for(i=0; i<ArraySize(aQuery); i++){
! 13524: char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
! 13525: int val = db_int(p, zSql);
! 13526: sqlite3_free(zSql);
! 13527: utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
1.2 misho 13528: }
1.4.2.2 ! misho 13529: sqlite3_free(zSchemaTab);
! 13530: sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
! 13531: utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
! 13532: return 0;
1.2 misho 13533: }
13534:
13535: /*
1.4.2.2 ! misho 13536: ** Print the current sqlite3_errmsg() value to stderr and return 1.
! 13537: */
! 13538: static int shellDatabaseError(sqlite3 *db){
! 13539: const char *zErr = sqlite3_errmsg(db);
! 13540: utf8_printf(stderr, "Error: %s\n", zErr);
! 13541: return 1;
! 13542: }
! 13543:
! 13544: /*
! 13545: ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
! 13546: ** if they match and FALSE (0) if they do not match.
1.2 misho 13547: **
1.4.2.2 ! misho 13548: ** Globbing rules:
! 13549: **
! 13550: ** '*' Matches any sequence of zero or more characters.
! 13551: **
! 13552: ** '?' Matches exactly one character.
! 13553: **
! 13554: ** [...] Matches one character from the enclosed list of
! 13555: ** characters.
! 13556: **
! 13557: ** [^...] Matches one character not in the enclosed list.
! 13558: **
! 13559: ** '#' Matches any sequence of one or more digits with an
! 13560: ** optional + or - sign in front
! 13561: **
! 13562: ** ' ' Any span of whitespace matches any other span of
! 13563: ** whitespace.
! 13564: **
! 13565: ** Extra whitespace at the end of z[] is ignored.
1.2 misho 13566: */
1.4.2.2 ! misho 13567: static int testcase_glob(const char *zGlob, const char *z){
! 13568: int c, c2;
! 13569: int invert;
! 13570: int seen;
! 13571:
! 13572: while( (c = (*(zGlob++)))!=0 ){
! 13573: if( IsSpace(c) ){
! 13574: if( !IsSpace(*z) ) return 0;
! 13575: while( IsSpace(*zGlob) ) zGlob++;
! 13576: while( IsSpace(*z) ) z++;
! 13577: }else if( c=='*' ){
! 13578: while( (c=(*(zGlob++))) == '*' || c=='?' ){
! 13579: if( c=='?' && (*(z++))==0 ) return 0;
! 13580: }
! 13581: if( c==0 ){
! 13582: return 1;
! 13583: }else if( c=='[' ){
! 13584: while( *z && testcase_glob(zGlob-1,z)==0 ){
! 13585: z++;
! 13586: }
! 13587: return (*z)!=0;
! 13588: }
! 13589: while( (c2 = (*(z++)))!=0 ){
! 13590: while( c2!=c ){
! 13591: c2 = *(z++);
! 13592: if( c2==0 ) return 0;
! 13593: }
! 13594: if( testcase_glob(zGlob,z) ) return 1;
! 13595: }
! 13596: return 0;
! 13597: }else if( c=='?' ){
! 13598: if( (*(z++))==0 ) return 0;
! 13599: }else if( c=='[' ){
! 13600: int prior_c = 0;
! 13601: seen = 0;
! 13602: invert = 0;
! 13603: c = *(z++);
! 13604: if( c==0 ) return 0;
! 13605: c2 = *(zGlob++);
! 13606: if( c2=='^' ){
! 13607: invert = 1;
! 13608: c2 = *(zGlob++);
! 13609: }
! 13610: if( c2==']' ){
! 13611: if( c==']' ) seen = 1;
! 13612: c2 = *(zGlob++);
! 13613: }
! 13614: while( c2 && c2!=']' ){
! 13615: if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
! 13616: c2 = *(zGlob++);
! 13617: if( c>=prior_c && c<=c2 ) seen = 1;
! 13618: prior_c = 0;
! 13619: }else{
! 13620: if( c==c2 ){
! 13621: seen = 1;
1.2 misho 13622: }
1.4.2.2 ! misho 13623: prior_c = c2;
1.2 misho 13624: }
1.4.2.2 ! misho 13625: c2 = *(zGlob++);
1.2 misho 13626: }
1.4.2.2 ! misho 13627: if( c2==0 || (seen ^ invert)==0 ) return 0;
! 13628: }else if( c=='#' ){
! 13629: if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
! 13630: if( !IsDigit(z[0]) ) return 0;
! 13631: z++;
! 13632: while( IsDigit(z[0]) ){ z++; }
! 13633: }else{
! 13634: if( c!=(*(z++)) ) return 0;
1.2 misho 13635: }
13636: }
1.4.2.2 ! misho 13637: while( IsSpace(*z) ){ z++; }
! 13638: return *z==0;
1.4 misho 13639: }
13640:
1.4.2.2 ! misho 13641:
1.4 misho 13642: /*
1.4.2.2 ! misho 13643: ** Compare the string as a command-line option with either one or two
! 13644: ** initial "-" characters.
1.4 misho 13645: */
1.4.2.2 ! misho 13646: static int optionMatch(const char *zStr, const char *zOpt){
! 13647: if( zStr[0]!='-' ) return 0;
! 13648: zStr++;
! 13649: if( zStr[0]=='-' ) zStr++;
! 13650: return strcmp(zStr, zOpt)==0;
1.4 misho 13651: }
13652:
13653: /*
1.4.2.2 ! misho 13654: ** Delete a file.
1.4 misho 13655: */
1.4.2.2 ! misho 13656: int shellDeleteFile(const char *zFilename){
! 13657: int rc;
! 13658: #ifdef _WIN32
! 13659: wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
! 13660: rc = _wunlink(z);
! 13661: sqlite3_free(z);
! 13662: #else
! 13663: rc = unlink(zFilename);
! 13664: #endif
! 13665: return rc;
! 13666: }
! 13667:
! 13668: /*
! 13669: ** Try to delete the temporary file (if there is one) and free the
! 13670: ** memory used to hold the name of the temp file.
! 13671: */
! 13672: static void clearTempFile(ShellState *p){
! 13673: if( p->zTempFile==0 ) return;
! 13674: if( p->doXdgOpen ) return;
! 13675: if( shellDeleteFile(p->zTempFile) ) return;
! 13676: sqlite3_free(p->zTempFile);
! 13677: p->zTempFile = 0;
! 13678: }
! 13679:
! 13680: /*
! 13681: ** Create a new temp file name with the given suffix.
! 13682: */
! 13683: static void newTempFile(ShellState *p, const char *zSuffix){
! 13684: clearTempFile(p);
! 13685: sqlite3_free(p->zTempFile);
! 13686: p->zTempFile = 0;
! 13687: if( p->db ){
! 13688: sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
! 13689: }
! 13690: if( p->zTempFile==0 ){
! 13691: sqlite3_uint64 r;
! 13692: sqlite3_randomness(sizeof(r), &r);
! 13693: p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
1.4 misho 13694: }else{
1.4.2.2 ! misho 13695: p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
1.4 misho 13696: }
1.4.2.2 ! misho 13697: if( p->zTempFile==0 ){
! 13698: raw_printf(stderr, "out of memory\n");
! 13699: exit(1);
1.4 misho 13700: }
1.2 misho 13701: }
13702:
1.4.2.2 ! misho 13703:
1.2 misho 13704: /*
1.4.2.2 ! misho 13705: ** The implementation of SQL scalar function fkey_collate_clause(), used
! 13706: ** by the ".lint fkey-indexes" command. This scalar function is always
! 13707: ** called with four arguments - the parent table name, the parent column name,
! 13708: ** the child table name and the child column name.
! 13709: **
! 13710: ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
! 13711: **
! 13712: ** If either of the named tables or columns do not exist, this function
! 13713: ** returns an empty string. An empty string is also returned if both tables
! 13714: ** and columns exist but have the same default collation sequence. Or,
! 13715: ** if both exist but the default collation sequences are different, this
! 13716: ** function returns the string " COLLATE <parent-collation>", where
! 13717: ** <parent-collation> is the default collation sequence of the parent column.
1.2 misho 13718: */
1.4.2.2 ! misho 13719: static void shellFkeyCollateClause(
! 13720: sqlite3_context *pCtx,
! 13721: int nVal,
! 13722: sqlite3_value **apVal
! 13723: ){
! 13724: sqlite3 *db = sqlite3_context_db_handle(pCtx);
! 13725: const char *zParent;
! 13726: const char *zParentCol;
! 13727: const char *zParentSeq;
! 13728: const char *zChild;
! 13729: const char *zChildCol;
! 13730: const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
! 13731: int rc;
! 13732:
! 13733: assert( nVal==4 );
! 13734: zParent = (const char*)sqlite3_value_text(apVal[0]);
! 13735: zParentCol = (const char*)sqlite3_value_text(apVal[1]);
! 13736: zChild = (const char*)sqlite3_value_text(apVal[2]);
! 13737: zChildCol = (const char*)sqlite3_value_text(apVal[3]);
! 13738:
! 13739: sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
! 13740: rc = sqlite3_table_column_metadata(
! 13741: db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
! 13742: );
! 13743: if( rc==SQLITE_OK ){
! 13744: rc = sqlite3_table_column_metadata(
! 13745: db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
! 13746: );
1.2 misho 13747: }
1.4.2.2 ! misho 13748:
! 13749: if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
! 13750: char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
! 13751: sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
! 13752: sqlite3_free(z);
! 13753: }
! 13754: }
! 13755:
! 13756:
! 13757: /*
! 13758: ** The implementation of dot-command ".lint fkey-indexes".
! 13759: */
! 13760: static int lintFkeyIndexes(
! 13761: ShellState *pState, /* Current shell tool state */
! 13762: char **azArg, /* Array of arguments passed to dot command */
! 13763: int nArg /* Number of entries in azArg[] */
! 13764: ){
! 13765: sqlite3 *db = pState->db; /* Database handle to query "main" db of */
! 13766: FILE *out = pState->out; /* Stream to write non-error output to */
! 13767: int bVerbose = 0; /* If -verbose is present */
! 13768: int bGroupByParent = 0; /* If -groupbyparent is present */
! 13769: int i; /* To iterate through azArg[] */
! 13770: const char *zIndent = ""; /* How much to indent CREATE INDEX by */
! 13771: int rc; /* Return code */
! 13772: sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
! 13773:
! 13774: /*
! 13775: ** This SELECT statement returns one row for each foreign key constraint
! 13776: ** in the schema of the main database. The column values are:
! 13777: **
! 13778: ** 0. The text of an SQL statement similar to:
! 13779: **
! 13780: ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
! 13781: **
! 13782: ** This SELECT is similar to the one that the foreign keys implementation
! 13783: ** needs to run internally on child tables. If there is an index that can
! 13784: ** be used to optimize this query, then it can also be used by the FK
! 13785: ** implementation to optimize DELETE or UPDATE statements on the parent
! 13786: ** table.
! 13787: **
! 13788: ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
! 13789: ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
! 13790: ** contains an index that can be used to optimize the query.
! 13791: **
! 13792: ** 2. Human readable text that describes the child table and columns. e.g.
! 13793: **
! 13794: ** "child_table(child_key1, child_key2)"
! 13795: **
! 13796: ** 3. Human readable text that describes the parent table and columns. e.g.
! 13797: **
! 13798: ** "parent_table(parent_key1, parent_key2)"
! 13799: **
! 13800: ** 4. A full CREATE INDEX statement for an index that could be used to
! 13801: ** optimize DELETE or UPDATE statements on the parent table. e.g.
! 13802: **
! 13803: ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
! 13804: **
! 13805: ** 5. The name of the parent table.
! 13806: **
! 13807: ** These six values are used by the C logic below to generate the report.
! 13808: */
! 13809: const char *zSql =
! 13810: "SELECT "
! 13811: " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
! 13812: " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
! 13813: " || fkey_collate_clause("
! 13814: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
! 13815: ", "
! 13816: " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
! 13817: " || group_concat('*=?', ' AND ') || ')'"
! 13818: ", "
! 13819: " s.name || '(' || group_concat(f.[from], ', ') || ')'"
! 13820: ", "
! 13821: " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
! 13822: ", "
! 13823: " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
! 13824: " || ' ON ' || quote(s.name) || '('"
! 13825: " || group_concat(quote(f.[from]) ||"
! 13826: " fkey_collate_clause("
! 13827: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
! 13828: " || ');'"
! 13829: ", "
! 13830: " f.[table] "
! 13831: "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
! 13832: "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
! 13833: "GROUP BY s.name, f.id "
! 13834: "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
! 13835: ;
! 13836: const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
! 13837:
! 13838: for(i=2; i<nArg; i++){
! 13839: int n = strlen30(azArg[i]);
! 13840: if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
! 13841: bVerbose = 1;
! 13842: }
! 13843: else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
! 13844: bGroupByParent = 1;
! 13845: zIndent = " ";
! 13846: }
! 13847: else{
! 13848: raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
! 13849: azArg[0], azArg[1]
! 13850: );
! 13851: return SQLITE_ERROR;
! 13852: }
! 13853: }
! 13854:
! 13855: /* Register the fkey_collate_clause() SQL function */
! 13856: rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
! 13857: 0, shellFkeyCollateClause, 0, 0
! 13858: );
! 13859:
! 13860:
! 13861: if( rc==SQLITE_OK ){
! 13862: rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
1.4 misho 13863: }
1.4.2.2 ! misho 13864: if( rc==SQLITE_OK ){
! 13865: sqlite3_bind_int(pSql, 1, bGroupByParent);
1.4 misho 13866: }
1.2 misho 13867:
1.4.2.2 ! misho 13868: if( rc==SQLITE_OK ){
! 13869: int rc2;
! 13870: char *zPrev = 0;
! 13871: while( SQLITE_ROW==sqlite3_step(pSql) ){
! 13872: int res = -1;
! 13873: sqlite3_stmt *pExplain = 0;
! 13874: const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
! 13875: const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
! 13876: const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
! 13877: const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
! 13878: const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
! 13879: const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
1.4.2.1 misho 13880:
1.4.2.2 ! misho 13881: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
! 13882: if( rc!=SQLITE_OK ) break;
! 13883: if( SQLITE_ROW==sqlite3_step(pExplain) ){
! 13884: const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
! 13885: res = (
! 13886: 0==sqlite3_strglob(zGlob, zPlan)
! 13887: || 0==sqlite3_strglob(zGlobIPK, zPlan)
! 13888: );
! 13889: }
! 13890: rc = sqlite3_finalize(pExplain);
! 13891: if( rc!=SQLITE_OK ) break;
1.3 misho 13892:
1.4.2.2 ! misho 13893: if( res<0 ){
! 13894: raw_printf(stderr, "Error: internal error");
! 13895: break;
! 13896: }else{
! 13897: if( bGroupByParent
! 13898: && (bVerbose || res==0)
! 13899: && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
! 13900: ){
! 13901: raw_printf(out, "-- Parent table %s\n", zParent);
! 13902: sqlite3_free(zPrev);
! 13903: zPrev = sqlite3_mprintf("%s", zParent);
! 13904: }
! 13905:
! 13906: if( res==0 ){
! 13907: raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
! 13908: }else if( bVerbose ){
! 13909: raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
! 13910: zIndent, zFrom, zTarget
! 13911: );
! 13912: }
! 13913: }
! 13914: }
! 13915: sqlite3_free(zPrev);
! 13916:
! 13917: if( rc!=SQLITE_OK ){
! 13918: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
! 13919: }
! 13920:
! 13921: rc2 = sqlite3_finalize(pSql);
! 13922: if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
! 13923: rc = rc2;
! 13924: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
1.3 misho 13925: }
1.4.2.2 ! misho 13926: }else{
! 13927: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
1.3 misho 13928: }
1.4.2.2 ! misho 13929:
! 13930: return rc;
1.3 misho 13931: }
13932:
13933: /*
1.4.2.2 ! misho 13934: ** Implementation of ".lint" dot command.
1.3 misho 13935: */
1.4.2.2 ! misho 13936: static int lintDotCommand(
! 13937: ShellState *pState, /* Current shell tool state */
! 13938: char **azArg, /* Array of arguments passed to dot command */
! 13939: int nArg /* Number of entries in azArg[] */
1.4 misho 13940: ){
1.4.2.2 ! misho 13941: int n;
! 13942: n = (nArg>=2 ? strlen30(azArg[1]) : 0);
! 13943: if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
! 13944: return lintFkeyIndexes(pState, azArg, nArg);
1.3 misho 13945:
1.4.2.2 ! misho 13946: usage:
! 13947: raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
! 13948: raw_printf(stderr, "Where sub-commands are:\n");
! 13949: raw_printf(stderr, " fkey-indexes\n");
! 13950: return SQLITE_ERROR;
1.3 misho 13951: }
13952:
1.4.2.2 ! misho 13953: #if !defined SQLITE_OMIT_VIRTUALTABLE
! 13954: static void shellPrepare(
! 13955: sqlite3 *db,
! 13956: int *pRc,
! 13957: const char *zSql,
! 13958: sqlite3_stmt **ppStmt
! 13959: ){
! 13960: *ppStmt = 0;
! 13961: if( *pRc==SQLITE_OK ){
! 13962: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
! 13963: if( rc!=SQLITE_OK ){
! 13964: raw_printf(stderr, "sql error: %s (%d)\n",
! 13965: sqlite3_errmsg(db), sqlite3_errcode(db)
! 13966: );
! 13967: *pRc = rc;
1.4 misho 13968: }
13969: }
13970: }
13971:
1.4.2.2 ! misho 13972: /*
! 13973: ** Create a prepared statement using printf-style arguments for the SQL.
1.4 misho 13974: **
1.4.2.2 ! misho 13975: ** This routine is could be marked "static". But it is not always used,
! 13976: ** depending on compile-time options. By omitting the "static", we avoid
! 13977: ** nuisance compiler warnings about "defined but not used".
! 13978: */
! 13979: void shellPreparePrintf(
! 13980: sqlite3 *db,
! 13981: int *pRc,
! 13982: sqlite3_stmt **ppStmt,
! 13983: const char *zFmt,
! 13984: ...
! 13985: ){
! 13986: *ppStmt = 0;
! 13987: if( *pRc==SQLITE_OK ){
! 13988: va_list ap;
! 13989: char *z;
! 13990: va_start(ap, zFmt);
! 13991: z = sqlite3_vmprintf(zFmt, ap);
! 13992: va_end(ap);
! 13993: if( z==0 ){
! 13994: *pRc = SQLITE_NOMEM;
! 13995: }else{
! 13996: shellPrepare(db, pRc, z, ppStmt);
! 13997: sqlite3_free(z);
1.4 misho 13998: }
13999: }
14000: }
14001:
1.4.2.2 ! misho 14002: /* Finalize the prepared statement created using shellPreparePrintf().
1.4 misho 14003: **
1.4.2.2 ! misho 14004: ** This routine is could be marked "static". But it is not always used,
! 14005: ** depending on compile-time options. By omitting the "static", we avoid
! 14006: ** nuisance compiler warnings about "defined but not used".
! 14007: */
! 14008: void shellFinalize(
! 14009: int *pRc,
! 14010: sqlite3_stmt *pStmt
! 14011: ){
! 14012: if( pStmt ){
! 14013: sqlite3 *db = sqlite3_db_handle(pStmt);
! 14014: int rc = sqlite3_finalize(pStmt);
! 14015: if( *pRc==SQLITE_OK ){
! 14016: if( rc!=SQLITE_OK ){
! 14017: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
! 14018: }
! 14019: *pRc = rc;
! 14020: }
1.4 misho 14021: }
1.4.2.2 ! misho 14022: }
! 14023:
! 14024: /* Reset the prepared statement created using shellPreparePrintf().
! 14025: **
! 14026: ** This routine is could be marked "static". But it is not always used,
! 14027: ** depending on compile-time options. By omitting the "static", we avoid
! 14028: ** nuisance compiler warnings about "defined but not used".
! 14029: */
! 14030: void shellReset(
! 14031: int *pRc,
! 14032: sqlite3_stmt *pStmt
! 14033: ){
! 14034: int rc = sqlite3_reset(pStmt);
! 14035: if( *pRc==SQLITE_OK ){
! 14036: if( rc!=SQLITE_OK ){
! 14037: sqlite3 *db = sqlite3_db_handle(pStmt);
! 14038: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
! 14039: }
! 14040: *pRc = rc;
1.4 misho 14041: }
14042: }
1.4.2.2 ! misho 14043: #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
! 14044:
! 14045: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
! 14046: /*********************************************************************************
! 14047: ** The ".archive" or ".ar" command.
! 14048: */
! 14049: /*
! 14050: ** Structure representing a single ".ar" command.
! 14051: */
! 14052: typedef struct ArCommand ArCommand;
! 14053: struct ArCommand {
! 14054: u8 eCmd; /* An AR_CMD_* value */
! 14055: u8 bVerbose; /* True if --verbose */
! 14056: u8 bZip; /* True if the archive is a ZIP */
! 14057: u8 bDryRun; /* True if --dry-run */
! 14058: u8 bAppend; /* True if --append */
! 14059: u8 fromCmdLine; /* Run from -A instead of .archive */
! 14060: int nArg; /* Number of command arguments */
! 14061: char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
! 14062: const char *zFile; /* --file argument, or NULL */
! 14063: const char *zDir; /* --directory argument, or NULL */
! 14064: char **azArg; /* Array of command arguments */
! 14065: ShellState *p; /* Shell state */
! 14066: sqlite3 *db; /* Database containing the archive */
! 14067: };
1.4 misho 14068:
14069: /*
1.4.2.2 ! misho 14070: ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
1.4 misho 14071: */
1.4.2.2 ! misho 14072: static int arUsage(FILE *f){
! 14073: showHelp(f,"archive");
! 14074: return SQLITE_ERROR;
! 14075: }
1.4 misho 14076:
1.4.2.2 ! misho 14077: /*
! 14078: ** Print an error message for the .ar command to stderr and return
! 14079: ** SQLITE_ERROR.
! 14080: */
! 14081: static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
! 14082: va_list ap;
! 14083: char *z;
! 14084: va_start(ap, zFmt);
! 14085: z = sqlite3_vmprintf(zFmt, ap);
! 14086: va_end(ap);
! 14087: utf8_printf(stderr, "Error: %s\n", z);
! 14088: if( pAr->fromCmdLine ){
! 14089: utf8_printf(stderr, "Use \"-A\" for more help\n");
! 14090: }else{
! 14091: utf8_printf(stderr, "Use \".archive --help\" for more help\n");
1.4 misho 14092: }
1.4.2.2 ! misho 14093: sqlite3_free(z);
! 14094: return SQLITE_ERROR;
! 14095: }
! 14096:
! 14097: /*
! 14098: ** Values for ArCommand.eCmd.
! 14099: */
! 14100: #define AR_CMD_CREATE 1
! 14101: #define AR_CMD_UPDATE 2
! 14102: #define AR_CMD_INSERT 3
! 14103: #define AR_CMD_EXTRACT 4
! 14104: #define AR_CMD_LIST 5
! 14105: #define AR_CMD_HELP 6
! 14106:
! 14107: /*
! 14108: ** Other (non-command) switches.
! 14109: */
! 14110: #define AR_SWITCH_VERBOSE 7
! 14111: #define AR_SWITCH_FILE 8
! 14112: #define AR_SWITCH_DIRECTORY 9
! 14113: #define AR_SWITCH_APPEND 10
! 14114: #define AR_SWITCH_DRYRUN 11
! 14115:
! 14116: static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
! 14117: switch( eSwitch ){
! 14118: case AR_CMD_CREATE:
! 14119: case AR_CMD_EXTRACT:
! 14120: case AR_CMD_LIST:
! 14121: case AR_CMD_UPDATE:
! 14122: case AR_CMD_INSERT:
! 14123: case AR_CMD_HELP:
! 14124: if( pAr->eCmd ){
! 14125: return arErrorMsg(pAr, "multiple command options");
1.4 misho 14126: }
1.4.2.2 ! misho 14127: pAr->eCmd = eSwitch;
1.4 misho 14128: break;
14129:
1.4.2.2 ! misho 14130: case AR_SWITCH_DRYRUN:
! 14131: pAr->bDryRun = 1;
! 14132: break;
! 14133: case AR_SWITCH_VERBOSE:
! 14134: pAr->bVerbose = 1;
! 14135: break;
! 14136: case AR_SWITCH_APPEND:
! 14137: pAr->bAppend = 1;
! 14138: /* Fall thru into --file */
! 14139: case AR_SWITCH_FILE:
! 14140: pAr->zFile = zArg;
! 14141: break;
! 14142: case AR_SWITCH_DIRECTORY:
! 14143: pAr->zDir = zArg;
! 14144: break;
! 14145: }
1.4 misho 14146:
1.4.2.2 ! misho 14147: return SQLITE_OK;
! 14148: }
1.4 misho 14149:
14150: /*
1.4.2.2 ! misho 14151: ** Parse the command line for an ".ar" command. The results are written into
! 14152: ** structure (*pAr). SQLITE_OK is returned if the command line is parsed
! 14153: ** successfully, otherwise an error message is written to stderr and
! 14154: ** SQLITE_ERROR returned.
1.4 misho 14155: */
1.4.2.2 ! misho 14156: static int arParseCommand(
! 14157: char **azArg, /* Array of arguments passed to dot command */
! 14158: int nArg, /* Number of entries in azArg[] */
! 14159: ArCommand *pAr /* Populate this object */
1.4 misho 14160: ){
1.4.2.2 ! misho 14161: struct ArSwitch {
! 14162: const char *zLong;
! 14163: char cShort;
! 14164: u8 eSwitch;
! 14165: u8 bArg;
! 14166: } aSwitch[] = {
! 14167: { "create", 'c', AR_CMD_CREATE, 0 },
! 14168: { "extract", 'x', AR_CMD_EXTRACT, 0 },
! 14169: { "insert", 'i', AR_CMD_INSERT, 0 },
! 14170: { "list", 't', AR_CMD_LIST, 0 },
! 14171: { "update", 'u', AR_CMD_UPDATE, 0 },
! 14172: { "help", 'h', AR_CMD_HELP, 0 },
! 14173: { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
! 14174: { "file", 'f', AR_SWITCH_FILE, 1 },
! 14175: { "append", 'a', AR_SWITCH_APPEND, 1 },
! 14176: { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
! 14177: { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
! 14178: };
! 14179: int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
! 14180: struct ArSwitch *pEnd = &aSwitch[nSwitch];
1.4 misho 14181:
1.4.2.2 ! misho 14182: if( nArg<=1 ){
! 14183: utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
! 14184: return arUsage(stderr);
! 14185: }else{
! 14186: char *z = azArg[1];
! 14187: if( z[0]!='-' ){
! 14188: /* Traditional style [tar] invocation */
! 14189: int i;
! 14190: int iArg = 2;
! 14191: for(i=0; z[i]; i++){
! 14192: const char *zArg = 0;
! 14193: struct ArSwitch *pOpt;
! 14194: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
! 14195: if( z[i]==pOpt->cShort ) break;
! 14196: }
! 14197: if( pOpt==pEnd ){
! 14198: return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
! 14199: }
! 14200: if( pOpt->bArg ){
! 14201: if( iArg>=nArg ){
! 14202: return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
! 14203: }
! 14204: zArg = azArg[iArg++];
! 14205: }
! 14206: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
1.4 misho 14207: }
1.4.2.2 ! misho 14208: pAr->nArg = nArg-iArg;
! 14209: if( pAr->nArg>0 ){
! 14210: pAr->azArg = &azArg[iArg];
! 14211: }
! 14212: }else{
! 14213: /* Non-traditional invocation */
! 14214: int iArg;
! 14215: for(iArg=1; iArg<nArg; iArg++){
! 14216: int n;
! 14217: z = azArg[iArg];
! 14218: if( z[0]!='-' ){
! 14219: /* All remaining command line words are command arguments. */
! 14220: pAr->azArg = &azArg[iArg];
! 14221: pAr->nArg = nArg-iArg;
! 14222: break;
! 14223: }
! 14224: n = strlen30(z);
! 14225:
! 14226: if( z[1]!='-' ){
! 14227: int i;
! 14228: /* One or more short options */
! 14229: for(i=1; i<n; i++){
! 14230: const char *zArg = 0;
! 14231: struct ArSwitch *pOpt;
! 14232: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
! 14233: if( z[i]==pOpt->cShort ) break;
! 14234: }
! 14235: if( pOpt==pEnd ){
! 14236: return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
! 14237: }
! 14238: if( pOpt->bArg ){
! 14239: if( i<(n-1) ){
! 14240: zArg = &z[i+1];
! 14241: i = n;
! 14242: }else{
! 14243: if( iArg>=(nArg-1) ){
! 14244: return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
! 14245: }
! 14246: zArg = azArg[++iArg];
! 14247: }
! 14248: }
! 14249: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
! 14250: }
! 14251: }else if( z[2]=='\0' ){
! 14252: /* A -- option, indicating that all remaining command line words
! 14253: ** are command arguments. */
! 14254: pAr->azArg = &azArg[iArg+1];
! 14255: pAr->nArg = nArg-iArg-1;
! 14256: break;
! 14257: }else{
! 14258: /* A long option */
! 14259: const char *zArg = 0; /* Argument for option, if any */
! 14260: struct ArSwitch *pMatch = 0; /* Matching option */
! 14261: struct ArSwitch *pOpt; /* Iterator */
! 14262: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
! 14263: const char *zLong = pOpt->zLong;
! 14264: if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
! 14265: if( pMatch ){
! 14266: return arErrorMsg(pAr, "ambiguous option: %s",z);
! 14267: }else{
! 14268: pMatch = pOpt;
! 14269: }
! 14270: }
! 14271: }
! 14272:
! 14273: if( pMatch==0 ){
! 14274: return arErrorMsg(pAr, "unrecognized option: %s", z);
! 14275: }
! 14276: if( pMatch->bArg ){
! 14277: if( iArg>=(nArg-1) ){
! 14278: return arErrorMsg(pAr, "option requires an argument: %s", z);
! 14279: }
! 14280: zArg = azArg[++iArg];
! 14281: }
! 14282: if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
! 14283: }
1.4 misho 14284: }
14285: }
14286: }
1.4.2.2 ! misho 14287:
! 14288: return SQLITE_OK;
1.4 misho 14289: }
14290:
14291: /*
1.4.2.2 ! misho 14292: ** This function assumes that all arguments within the ArCommand.azArg[]
! 14293: ** array refer to archive members, as for the --extract or --list commands.
! 14294: ** It checks that each of them are present. If any specified file is not
! 14295: ** present in the archive, an error is printed to stderr and an error
! 14296: ** code returned. Otherwise, if all specified arguments are present in
! 14297: ** the archive, SQLITE_OK is returned.
! 14298: **
! 14299: ** This function strips any trailing '/' characters from each argument.
! 14300: ** This is consistent with the way the [tar] command seems to work on
! 14301: ** Linux.
! 14302: */
! 14303: static int arCheckEntries(ArCommand *pAr){
! 14304: int rc = SQLITE_OK;
! 14305: if( pAr->nArg ){
! 14306: int i, j;
! 14307: sqlite3_stmt *pTest = 0;
! 14308:
! 14309: shellPreparePrintf(pAr->db, &rc, &pTest,
! 14310: "SELECT name FROM %s WHERE name=$name",
! 14311: pAr->zSrcTable
! 14312: );
! 14313: j = sqlite3_bind_parameter_index(pTest, "$name");
! 14314: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
! 14315: char *z = pAr->azArg[i];
! 14316: int n = strlen30(z);
! 14317: int bOk = 0;
! 14318: while( n>0 && z[n-1]=='/' ) n--;
! 14319: z[n] = '\0';
! 14320: sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
! 14321: if( SQLITE_ROW==sqlite3_step(pTest) ){
! 14322: bOk = 1;
! 14323: }
! 14324: shellReset(&rc, pTest);
! 14325: if( rc==SQLITE_OK && bOk==0 ){
! 14326: utf8_printf(stderr, "not found in archive: %s\n", z);
! 14327: rc = SQLITE_ERROR;
! 14328: }
! 14329: }
! 14330: shellFinalize(&rc, pTest);
1.4 misho 14331: }
1.4.2.2 ! misho 14332: return rc;
1.4 misho 14333: }
14334:
14335: /*
1.4.2.2 ! misho 14336: ** Format a WHERE clause that can be used against the "sqlar" table to
! 14337: ** identify all archive members that match the command arguments held
! 14338: ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
! 14339: ** The caller is responsible for eventually calling sqlite3_free() on
! 14340: ** any non-NULL (*pzWhere) value.
! 14341: */
! 14342: static void arWhereClause(
! 14343: int *pRc,
! 14344: ArCommand *pAr,
! 14345: char **pzWhere /* OUT: New WHERE clause */
! 14346: ){
! 14347: char *zWhere = 0;
! 14348: if( *pRc==SQLITE_OK ){
! 14349: if( pAr->nArg==0 ){
! 14350: zWhere = sqlite3_mprintf("1");
! 14351: }else{
! 14352: int i;
! 14353: const char *zSep = "";
! 14354: for(i=0; i<pAr->nArg; i++){
! 14355: const char *z = pAr->azArg[i];
! 14356: zWhere = sqlite3_mprintf(
! 14357: "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
! 14358: zWhere, zSep, z, strlen30(z)+1, z
! 14359: );
! 14360: if( zWhere==0 ){
! 14361: *pRc = SQLITE_NOMEM;
! 14362: break;
! 14363: }
! 14364: zSep = " OR ";
! 14365: }
! 14366: }
1.4 misho 14367: }
1.4.2.2 ! misho 14368: *pzWhere = zWhere;
1.4 misho 14369: }
14370:
14371: /*
1.4.2.2 ! misho 14372: ** Implementation of .ar "lisT" command.
1.4 misho 14373: */
1.4.2.2 ! misho 14374: static int arListCommand(ArCommand *pAr){
! 14375: const char *zSql = "SELECT %s FROM %s WHERE %s";
! 14376: const char *azCols[] = {
! 14377: "name",
! 14378: "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
! 14379: };
! 14380:
! 14381: char *zWhere = 0;
! 14382: sqlite3_stmt *pSql = 0;
! 14383: int rc;
! 14384:
! 14385: rc = arCheckEntries(pAr);
! 14386: arWhereClause(&rc, pAr, &zWhere);
! 14387:
! 14388: shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
! 14389: pAr->zSrcTable, zWhere);
! 14390: if( pAr->bDryRun ){
! 14391: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
! 14392: }else{
! 14393: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
! 14394: if( pAr->bVerbose ){
! 14395: utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
! 14396: sqlite3_column_text(pSql, 0),
! 14397: sqlite3_column_int(pSql, 1),
! 14398: sqlite3_column_text(pSql, 2),
! 14399: sqlite3_column_text(pSql, 3)
! 14400: );
! 14401: }else{
! 14402: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
! 14403: }
! 14404: }
1.4 misho 14405: }
1.4.2.2 ! misho 14406: shellFinalize(&rc, pSql);
! 14407: sqlite3_free(zWhere);
! 14408: return rc;
1.4 misho 14409: }
14410:
14411:
14412: /*
1.4.2.2 ! misho 14413: ** Implementation of .ar "eXtract" command.
1.4 misho 14414: */
1.4.2.2 ! misho 14415: static int arExtractCommand(ArCommand *pAr){
! 14416: const char *zSql1 =
! 14417: "SELECT "
! 14418: " ($dir || name),"
! 14419: " writefile(($dir || name), %s, mode, mtime) "
! 14420: "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
! 14421: " AND name NOT GLOB '*..[/\\]*'";
! 14422:
! 14423: const char *azExtraArg[] = {
! 14424: "sqlar_uncompress(data, sz)",
! 14425: "data"
1.4 misho 14426: };
1.4.2.2 ! misho 14427:
! 14428: sqlite3_stmt *pSql = 0;
! 14429: int rc = SQLITE_OK;
! 14430: char *zDir = 0;
! 14431: char *zWhere = 0;
! 14432: int i, j;
! 14433:
! 14434: /* If arguments are specified, check that they actually exist within
! 14435: ** the archive before proceeding. And formulate a WHERE clause to
! 14436: ** match them. */
! 14437: rc = arCheckEntries(pAr);
! 14438: arWhereClause(&rc, pAr, &zWhere);
! 14439:
! 14440: if( rc==SQLITE_OK ){
! 14441: if( pAr->zDir ){
! 14442: zDir = sqlite3_mprintf("%s/", pAr->zDir);
! 14443: }else{
! 14444: zDir = sqlite3_mprintf("");
! 14445: }
! 14446: if( zDir==0 ) rc = SQLITE_NOMEM;
1.4 misho 14447: }
1.4.2.2 ! misho 14448:
! 14449: shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
! 14450: azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
! 14451: );
! 14452:
! 14453: if( rc==SQLITE_OK ){
! 14454: j = sqlite3_bind_parameter_index(pSql, "$dir");
! 14455: sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
! 14456:
! 14457: /* Run the SELECT statement twice. The first time, writefile() is called
! 14458: ** for all archive members that should be extracted. The second time,
! 14459: ** only for the directories. This is because the timestamps for
! 14460: ** extracted directories must be reset after they are populated (as
! 14461: ** populating them changes the timestamp). */
! 14462: for(i=0; i<2; i++){
! 14463: j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
! 14464: sqlite3_bind_int(pSql, j, i);
! 14465: if( pAr->bDryRun ){
! 14466: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
! 14467: }else{
! 14468: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
! 14469: if( i==0 && pAr->bVerbose ){
! 14470: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
! 14471: }
! 14472: }
1.4 misho 14473: }
1.4.2.2 ! misho 14474: shellReset(&rc, pSql);
1.4 misho 14475: }
1.4.2.2 ! misho 14476: shellFinalize(&rc, pSql);
1.4 misho 14477: }
14478:
1.4.2.2 ! misho 14479: sqlite3_free(zDir);
! 14480: sqlite3_free(zWhere);
! 14481: return rc;
1.4 misho 14482: }
14483:
1.4.2.1 misho 14484: /*
1.4.2.2 ! misho 14485: ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
1.4.2.1 misho 14486: */
1.4.2.2 ! misho 14487: static int arExecSql(ArCommand *pAr, const char *zSql){
! 14488: int rc;
! 14489: if( pAr->bDryRun ){
! 14490: utf8_printf(pAr->p->out, "%s\n", zSql);
! 14491: rc = SQLITE_OK;
! 14492: }else{
! 14493: char *zErr = 0;
! 14494: rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
! 14495: if( zErr ){
! 14496: utf8_printf(stdout, "ERROR: %s\n", zErr);
! 14497: sqlite3_free(zErr);
! 14498: }
! 14499: }
! 14500: return rc;
1.4.2.1 misho 14501: }
14502:
1.4.2.2 ! misho 14503:
1.4.2.1 misho 14504: /*
1.4.2.2 ! misho 14505: ** Implementation of .ar "create", "insert", and "update" commands.
1.4.2.1 misho 14506: **
1.4.2.2 ! misho 14507: ** create -> Create a new SQL archive
! 14508: ** insert -> Insert or reinsert all files listed
! 14509: ** update -> Insert files that have changed or that were not
! 14510: ** previously in the archive
1.4.2.1 misho 14511: **
1.4.2.2 ! misho 14512: ** Create the "sqlar" table in the database if it does not already exist.
! 14513: ** Then add each file in the azFile[] array to the archive. Directories
! 14514: ** are added recursively. If argument bVerbose is non-zero, a message is
! 14515: ** printed on stdout for each file archived.
1.4.2.1 misho 14516: **
1.4.2.2 ! misho 14517: ** The create command is the same as update, except that it drops
! 14518: ** any existing "sqlar" table before beginning. The "insert" command
! 14519: ** always overwrites every file named on the command-line, where as
! 14520: ** "update" only overwrites if the size or mtime or mode has changed.
! 14521: */
! 14522: static int arCreateOrUpdateCommand(
! 14523: ArCommand *pAr, /* Command arguments and options */
! 14524: int bUpdate, /* true for a --create. */
! 14525: int bOnlyIfChanged /* Only update if file has changed */
! 14526: ){
! 14527: const char *zCreate =
! 14528: "CREATE TABLE IF NOT EXISTS sqlar(\n"
! 14529: " name TEXT PRIMARY KEY, -- name of the file\n"
! 14530: " mode INT, -- access permissions\n"
! 14531: " mtime INT, -- last modification time\n"
! 14532: " sz INT, -- original file size\n"
! 14533: " data BLOB -- compressed content\n"
! 14534: ")";
! 14535: const char *zDrop = "DROP TABLE IF EXISTS sqlar";
! 14536: const char *zInsertFmt[2] = {
! 14537: "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
! 14538: " SELECT\n"
! 14539: " %s,\n"
! 14540: " mode,\n"
! 14541: " mtime,\n"
! 14542: " CASE substr(lsmode(mode),1,1)\n"
! 14543: " WHEN '-' THEN length(data)\n"
! 14544: " WHEN 'd' THEN 0\n"
! 14545: " ELSE -1 END,\n"
! 14546: " sqlar_compress(data)\n"
! 14547: " FROM fsdir(%Q,%Q) AS disk\n"
! 14548: " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
! 14549: ,
! 14550: "REPLACE INTO %s(name,mode,mtime,data)\n"
! 14551: " SELECT\n"
! 14552: " %s,\n"
! 14553: " mode,\n"
! 14554: " mtime,\n"
! 14555: " data\n"
! 14556: " FROM fsdir(%Q,%Q) AS disk\n"
! 14557: " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
! 14558: };
! 14559: int i; /* For iterating through azFile[] */
! 14560: int rc; /* Return code */
! 14561: const char *zTab = 0; /* SQL table into which to insert */
! 14562: char *zSql;
! 14563: char zTemp[50];
! 14564: char *zExists = 0;
1.4.2.1 misho 14565:
1.4.2.2 ! misho 14566: arExecSql(pAr, "PRAGMA page_size=512");
! 14567: rc = arExecSql(pAr, "SAVEPOINT ar;");
! 14568: if( rc!=SQLITE_OK ) return rc;
! 14569: zTemp[0] = 0;
! 14570: if( pAr->bZip ){
! 14571: /* Initialize the zipfile virtual table, if necessary */
! 14572: if( pAr->zFile ){
! 14573: sqlite3_uint64 r;
! 14574: sqlite3_randomness(sizeof(r),&r);
! 14575: sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
! 14576: zTab = zTemp;
! 14577: zSql = sqlite3_mprintf(
! 14578: "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
! 14579: zTab, pAr->zFile
! 14580: );
! 14581: rc = arExecSql(pAr, zSql);
! 14582: sqlite3_free(zSql);
! 14583: }else{
! 14584: zTab = "zip";
! 14585: }
! 14586: }else{
! 14587: /* Initialize the table for an SQLAR */
! 14588: zTab = "sqlar";
! 14589: if( bUpdate==0 ){
! 14590: rc = arExecSql(pAr, zDrop);
! 14591: if( rc!=SQLITE_OK ) goto end_ar_transaction;
! 14592: }
! 14593: rc = arExecSql(pAr, zCreate);
! 14594: }
! 14595: if( bOnlyIfChanged ){
! 14596: zExists = sqlite3_mprintf(
! 14597: " AND NOT EXISTS("
! 14598: "SELECT 1 FROM %s AS mem"
! 14599: " WHERE mem.name=disk.name"
! 14600: " AND mem.mtime=disk.mtime"
! 14601: " AND mem.mode=disk.mode)", zTab);
! 14602: }else{
! 14603: zExists = sqlite3_mprintf("");
! 14604: }
! 14605: if( zExists==0 ) rc = SQLITE_NOMEM;
! 14606: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
! 14607: char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
! 14608: pAr->bVerbose ? "shell_putsnl(name)" : "name",
! 14609: pAr->azArg[i], pAr->zDir, zExists);
! 14610: rc = arExecSql(pAr, zSql2);
! 14611: sqlite3_free(zSql2);
! 14612: }
! 14613: end_ar_transaction:
! 14614: if( rc!=SQLITE_OK ){
! 14615: sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
! 14616: }else{
! 14617: rc = arExecSql(pAr, "RELEASE ar;");
! 14618: if( pAr->bZip && pAr->zFile ){
! 14619: zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
! 14620: arExecSql(pAr, zSql);
! 14621: sqlite3_free(zSql);
! 14622: }
! 14623: }
! 14624: sqlite3_free(zExists);
! 14625: return rc;
! 14626: }
! 14627:
! 14628: /*
! 14629: ** Implementation of ".ar" dot command.
! 14630: */
! 14631: static int arDotCommand(
! 14632: ShellState *pState, /* Current shell tool state */
! 14633: int fromCmdLine, /* True if -A command-line option, not .ar cmd */
! 14634: char **azArg, /* Array of arguments passed to dot command */
! 14635: int nArg /* Number of entries in azArg[] */
! 14636: ){
! 14637: ArCommand cmd;
! 14638: int rc;
! 14639: memset(&cmd, 0, sizeof(cmd));
! 14640: cmd.fromCmdLine = fromCmdLine;
! 14641: rc = arParseCommand(azArg, nArg, &cmd);
! 14642: if( rc==SQLITE_OK ){
! 14643: int eDbType = SHELL_OPEN_UNSPEC;
! 14644: cmd.p = pState;
! 14645: cmd.db = pState->db;
! 14646: if( cmd.zFile ){
! 14647: eDbType = deduceDatabaseType(cmd.zFile, 1);
! 14648: }else{
! 14649: eDbType = pState->openMode;
! 14650: }
! 14651: if( eDbType==SHELL_OPEN_ZIPFILE ){
! 14652: if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
! 14653: if( cmd.zFile==0 ){
! 14654: cmd.zSrcTable = sqlite3_mprintf("zip");
1.4.2.1 misho 14655: }else{
1.4.2.2 ! misho 14656: cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
1.4.2.1 misho 14657: }
14658: }
1.4.2.2 ! misho 14659: cmd.bZip = 1;
! 14660: }else if( cmd.zFile ){
! 14661: int flags;
! 14662: if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
! 14663: if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
! 14664: || cmd.eCmd==AR_CMD_UPDATE ){
! 14665: flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
! 14666: }else{
! 14667: flags = SQLITE_OPEN_READONLY;
! 14668: }
! 14669: cmd.db = 0;
! 14670: if( cmd.bDryRun ){
! 14671: utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
! 14672: eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
! 14673: }
! 14674: rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
! 14675: eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
! 14676: if( rc!=SQLITE_OK ){
! 14677: utf8_printf(stderr, "cannot open file: %s (%s)\n",
! 14678: cmd.zFile, sqlite3_errmsg(cmd.db)
! 14679: );
! 14680: goto end_ar_command;
! 14681: }
! 14682: sqlite3_fileio_init(cmd.db, 0, 0);
! 14683: sqlite3_sqlar_init(cmd.db, 0, 0);
! 14684: sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
! 14685: shellPutsFunc, 0, 0);
! 14686:
! 14687: }
! 14688: if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
! 14689: if( cmd.eCmd!=AR_CMD_CREATE
! 14690: && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
! 14691: ){
! 14692: utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
! 14693: rc = SQLITE_ERROR;
! 14694: goto end_ar_command;
! 14695: }
! 14696: cmd.zSrcTable = sqlite3_mprintf("sqlar");
! 14697: }
! 14698:
! 14699: switch( cmd.eCmd ){
! 14700: case AR_CMD_CREATE:
! 14701: rc = arCreateOrUpdateCommand(&cmd, 0, 0);
! 14702: break;
! 14703:
! 14704: case AR_CMD_EXTRACT:
! 14705: rc = arExtractCommand(&cmd);
! 14706: break;
! 14707:
! 14708: case AR_CMD_LIST:
! 14709: rc = arListCommand(&cmd);
! 14710: break;
! 14711:
! 14712: case AR_CMD_HELP:
! 14713: arUsage(pState->out);
! 14714: break;
! 14715:
! 14716: case AR_CMD_INSERT:
! 14717: rc = arCreateOrUpdateCommand(&cmd, 1, 0);
! 14718: break;
! 14719:
! 14720: default:
! 14721: assert( cmd.eCmd==AR_CMD_UPDATE );
! 14722: rc = arCreateOrUpdateCommand(&cmd, 1, 1);
! 14723: break;
! 14724: }
! 14725: }
! 14726: end_ar_command:
! 14727: if( cmd.db!=pState->db ){
! 14728: close_db(cmd.db);
! 14729: }
! 14730: sqlite3_free(cmd.zSrcTable);
! 14731:
! 14732: return rc;
! 14733: }
! 14734: /* End of the ".archive" or ".ar" command logic
! 14735: **********************************************************************************/
! 14736: #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
! 14737:
! 14738: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 14739: /*
! 14740: ** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
! 14741: ** Otherwise, the SQL statement or statements in zSql are executed using
! 14742: ** database connection db and the error code written to *pRc before
! 14743: ** this function returns.
! 14744: */
! 14745: static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
! 14746: int rc = *pRc;
! 14747: if( rc==SQLITE_OK ){
! 14748: char *zErr = 0;
! 14749: rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
! 14750: if( rc!=SQLITE_OK ){
! 14751: raw_printf(stderr, "SQL error: %s\n", zErr);
! 14752: }
! 14753: *pRc = rc;
! 14754: }
! 14755: }
! 14756:
! 14757: /*
! 14758: ** Like shellExec(), except that zFmt is a printf() style format string.
! 14759: */
! 14760: static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
! 14761: char *z = 0;
! 14762: if( *pRc==SQLITE_OK ){
! 14763: va_list ap;
! 14764: va_start(ap, zFmt);
! 14765: z = sqlite3_vmprintf(zFmt, ap);
! 14766: va_end(ap);
! 14767: if( z==0 ){
! 14768: *pRc = SQLITE_NOMEM;
1.4.2.1 misho 14769: }else{
1.4.2.2 ! misho 14770: shellExec(db, pRc, z);
1.4.2.1 misho 14771: }
1.4.2.2 ! misho 14772: sqlite3_free(z);
1.4.2.1 misho 14773: }
14774: }
14775:
1.4.2.2 ! misho 14776: /*
! 14777: ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
! 14778: ** Otherwise, an attempt is made to allocate, zero and return a pointer
! 14779: ** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
! 14780: ** to SQLITE_NOMEM and NULL returned.
! 14781: */
! 14782: static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
! 14783: void *pRet = 0;
! 14784: if( *pRc==SQLITE_OK ){
! 14785: pRet = sqlite3_malloc64(nByte);
! 14786: if( pRet==0 ){
! 14787: *pRc = SQLITE_NOMEM;
! 14788: }else{
! 14789: memset(pRet, 0, nByte);
! 14790: }
! 14791: }
! 14792: return pRet;
! 14793: }
1.4 misho 14794:
14795: /*
1.4.2.2 ! misho 14796: ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
! 14797: ** Otherwise, zFmt is treated as a printf() style string. The result of
! 14798: ** formatting it along with any trailing arguments is written into a
! 14799: ** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
! 14800: ** It is the responsibility of the caller to eventually free this buffer
! 14801: ** using a call to sqlite3_free().
! 14802: **
! 14803: ** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
! 14804: ** pointer returned.
! 14805: */
! 14806: static char *shellMPrintf(int *pRc, const char *zFmt, ...){
! 14807: char *z = 0;
! 14808: if( *pRc==SQLITE_OK ){
! 14809: va_list ap;
! 14810: va_start(ap, zFmt);
! 14811: z = sqlite3_vmprintf(zFmt, ap);
! 14812: va_end(ap);
! 14813: if( z==0 ){
! 14814: *pRc = SQLITE_NOMEM;
! 14815: }
! 14816: }
! 14817: return z;
1.4 misho 14818: }
14819:
14820: /*
1.4.2.2 ! misho 14821: ** When running the ".recover" command, each output table, and the special
! 14822: ** orphaned row table if it is required, is represented by an instance
! 14823: ** of the following struct.
1.4.2.1 misho 14824: */
1.4.2.2 ! misho 14825: typedef struct RecoverTable RecoverTable;
! 14826: struct RecoverTable {
! 14827: char *zQuoted; /* Quoted version of table name */
! 14828: int nCol; /* Number of columns in table */
! 14829: char **azlCol; /* Array of column lists */
! 14830: int iPk; /* Index of IPK column */
! 14831: };
1.4.2.1 misho 14832:
1.4.2.2 ! misho 14833: /*
! 14834: ** Free a RecoverTable object allocated by recoverFindTable() or
! 14835: ** recoverOrphanTable().
! 14836: */
! 14837: static void recoverFreeTable(RecoverTable *pTab){
! 14838: if( pTab ){
! 14839: sqlite3_free(pTab->zQuoted);
! 14840: if( pTab->azlCol ){
! 14841: int i;
! 14842: for(i=0; i<=pTab->nCol; i++){
! 14843: sqlite3_free(pTab->azlCol[i]);
! 14844: }
! 14845: sqlite3_free(pTab->azlCol);
! 14846: }
! 14847: sqlite3_free(pTab);
! 14848: }
! 14849: }
1.4.2.1 misho 14850:
14851: /*
1.4.2.2 ! misho 14852: ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
! 14853: ** Otherwise, it allocates and returns a RecoverTable object based on the
! 14854: ** final four arguments passed to this function. It is the responsibility
! 14855: ** of the caller to eventually free the returned object using
! 14856: ** recoverFreeTable().
1.4.2.1 misho 14857: */
1.4.2.2 ! misho 14858: static RecoverTable *recoverNewTable(
! 14859: int *pRc, /* IN/OUT: Error code */
! 14860: const char *zName, /* Name of table */
! 14861: const char *zSql, /* CREATE TABLE statement */
! 14862: int bIntkey,
! 14863: int nCol
1.4.2.1 misho 14864: ){
1.4.2.2 ! misho 14865: sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
! 14866: int rc = *pRc;
! 14867: RecoverTable *pTab = 0;
1.4.2.1 misho 14868:
1.4.2.2 ! misho 14869: pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
1.4.2.1 misho 14870: if( rc==SQLITE_OK ){
1.4.2.2 ! misho 14871: int nSqlCol = 0;
! 14872: int bSqlIntkey = 0;
! 14873: sqlite3_stmt *pStmt = 0;
! 14874:
! 14875: rc = sqlite3_open("", &dbtmp);
! 14876: if( rc==SQLITE_OK ){
! 14877: rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
! 14878: }
! 14879: if( rc==SQLITE_OK ){
! 14880: rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
! 14881: if( rc==SQLITE_ERROR ){
! 14882: rc = SQLITE_OK;
! 14883: goto finished;
! 14884: }
! 14885: }
! 14886: shellPreparePrintf(dbtmp, &rc, &pStmt,
! 14887: "SELECT count(*) FROM pragma_table_info(%Q)", zName
! 14888: );
! 14889: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 14890: nSqlCol = sqlite3_column_int(pStmt, 0);
! 14891: }
! 14892: shellFinalize(&rc, pStmt);
! 14893:
! 14894: if( rc!=SQLITE_OK || nSqlCol<nCol ){
! 14895: goto finished;
! 14896: }
! 14897:
! 14898: shellPreparePrintf(dbtmp, &rc, &pStmt,
! 14899: "SELECT ("
! 14900: " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
! 14901: ") FROM sqlite_master WHERE name = %Q", zName
1.4.2.1 misho 14902: );
1.4.2.2 ! misho 14903: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 14904: bSqlIntkey = sqlite3_column_int(pStmt, 0);
! 14905: }
! 14906: shellFinalize(&rc, pStmt);
! 14907:
! 14908: if( bIntkey==bSqlIntkey ){
! 14909: int i;
! 14910: const char *zPk = "_rowid_";
! 14911: sqlite3_stmt *pPkFinder = 0;
! 14912:
! 14913: /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
! 14914: ** set zPk to the name of the PK column, and pTab->iPk to the index
! 14915: ** of the column, where columns are 0-numbered from left to right.
! 14916: ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
! 14917: ** leave zPk as "_rowid_" and pTab->iPk at -2. */
! 14918: pTab->iPk = -2;
! 14919: if( bIntkey ){
! 14920: shellPreparePrintf(dbtmp, &rc, &pPkFinder,
! 14921: "SELECT cid, name FROM pragma_table_info(%Q) "
! 14922: " WHERE pk=1 AND type='integer' COLLATE nocase"
! 14923: " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
! 14924: , zName, zName
! 14925: );
! 14926: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
! 14927: pTab->iPk = sqlite3_column_int(pPkFinder, 0);
! 14928: zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
! 14929: }
! 14930: }
! 14931:
! 14932: pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);
! 14933: pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
! 14934: pTab->nCol = nSqlCol;
! 14935:
! 14936: if( bIntkey ){
! 14937: pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
! 14938: }else{
! 14939: pTab->azlCol[0] = shellMPrintf(&rc, "");
! 14940: }
! 14941: i = 1;
! 14942: shellPreparePrintf(dbtmp, &rc, &pStmt,
! 14943: "SELECT %Q || group_concat(name, ', ') "
! 14944: " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
! 14945: "FROM pragma_table_info(%Q)",
! 14946: bIntkey ? ", " : "", pTab->iPk,
! 14947: bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
! 14948: zName
! 14949: );
! 14950: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 14951: const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
! 14952: pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
! 14953: i++;
! 14954: }
! 14955: shellFinalize(&rc, pStmt);
! 14956:
! 14957: shellFinalize(&rc, pPkFinder);
! 14958: }
1.4.2.1 misho 14959: }
14960:
1.4.2.2 ! misho 14961: finished:
! 14962: sqlite3_close(dbtmp);
! 14963: *pRc = rc;
! 14964: if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
! 14965: recoverFreeTable(pTab);
! 14966: pTab = 0;
1.4.2.1 misho 14967: }
1.4.2.2 ! misho 14968: return pTab;
1.4.2.1 misho 14969: }
14970:
1.4.2.2 ! misho 14971: /*
! 14972: ** This function is called to search the schema recovered from the
! 14973: ** sqlite_master table of the (possibly) corrupt database as part
! 14974: ** of a ".recover" command. Specifically, for a table with root page
! 14975: ** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
! 14976: ** table must be a WITHOUT ROWID table, or if non-zero, not one of
! 14977: ** those.
! 14978: **
! 14979: ** If a table is found, a (RecoverTable*) object is returned. Or, if
! 14980: ** no such table is found, but bIntkey is false and iRoot is the
! 14981: ** root page of an index in the recovered schema, then (*pbNoop) is
! 14982: ** set to true and NULL returned. Or, if there is no such table or
! 14983: ** index, NULL is returned and (*pbNoop) set to 0, indicating that
! 14984: ** the caller should write data to the orphans table.
! 14985: */
! 14986: static RecoverTable *recoverFindTable(
! 14987: ShellState *pState, /* Shell state object */
! 14988: int *pRc, /* IN/OUT: Error code */
! 14989: int iRoot, /* Root page of table */
! 14990: int bIntkey, /* True for an intkey table */
! 14991: int nCol, /* Number of columns in table */
! 14992: int *pbNoop /* OUT: True if iRoot is root of index */
! 14993: ){
! 14994: sqlite3_stmt *pStmt = 0;
! 14995: RecoverTable *pRet = 0;
! 14996: int bNoop = 0;
! 14997: const char *zSql = 0;
! 14998: const char *zName = 0;
! 14999:
! 15000: /* Search the recovered schema for an object with root page iRoot. */
! 15001: shellPreparePrintf(pState->db, pRc, &pStmt,
! 15002: "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
! 15003: );
! 15004: while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 15005: const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
! 15006: if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
! 15007: bNoop = 1;
! 15008: break;
! 15009: }
! 15010: if( sqlite3_stricmp(zType, "table")==0 ){
! 15011: zName = (const char*)sqlite3_column_text(pStmt, 1);
! 15012: zSql = (const char*)sqlite3_column_text(pStmt, 2);
! 15013: pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
! 15014: break;
! 15015: }
! 15016: }
! 15017:
! 15018: shellFinalize(pRc, pStmt);
! 15019: *pbNoop = bNoop;
! 15020: return pRet;
! 15021: }
1.4.2.1 misho 15022:
15023: /*
1.4.2.2 ! misho 15024: ** Return a RecoverTable object representing the orphans table.
1.4.2.1 misho 15025: */
1.4.2.2 ! misho 15026: static RecoverTable *recoverOrphanTable(
! 15027: ShellState *pState, /* Shell state object */
! 15028: int *pRc, /* IN/OUT: Error code */
! 15029: const char *zLostAndFound, /* Base name for orphans table */
! 15030: int nCol /* Number of user data columns */
1.4.2.1 misho 15031: ){
1.4.2.2 ! misho 15032: RecoverTable *pTab = 0;
! 15033: if( nCol>=0 && *pRc==SQLITE_OK ){
! 15034: int i;
1.4.2.1 misho 15035:
1.4.2.2 ! misho 15036: /* This block determines the name of the orphan table. The prefered
! 15037: ** name is zLostAndFound. But if that clashes with another name
! 15038: ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
! 15039: ** and so on until a non-clashing name is found. */
! 15040: int iTab = 0;
! 15041: char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
! 15042: sqlite3_stmt *pTest = 0;
! 15043: shellPrepare(pState->db, pRc,
! 15044: "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
! 15045: );
! 15046: if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
! 15047: while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
! 15048: shellReset(pRc, pTest);
! 15049: sqlite3_free(zTab);
! 15050: zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
! 15051: sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
! 15052: }
! 15053: shellFinalize(pRc, pTest);
! 15054:
! 15055: pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
! 15056: if( pTab ){
! 15057: pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);
! 15058: pTab->nCol = nCol;
! 15059: pTab->iPk = -2;
! 15060: if( nCol>0 ){
! 15061: pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
! 15062: if( pTab->azlCol ){
! 15063: pTab->azlCol[nCol] = shellMPrintf(pRc, "");
! 15064: for(i=nCol-1; i>=0; i--){
! 15065: pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
! 15066: }
! 15067: }
! 15068: }
! 15069:
! 15070: if( *pRc!=SQLITE_OK ){
! 15071: recoverFreeTable(pTab);
! 15072: pTab = 0;
! 15073: }else{
! 15074: raw_printf(pState->out,
! 15075: "CREATE TABLE %s(rootpgno INTEGER, "
! 15076: "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
! 15077: );
! 15078: for(i=0; i<nCol; i++){
! 15079: raw_printf(pState->out, ", c%d", i);
! 15080: }
! 15081: raw_printf(pState->out, ");\n");
! 15082: }
! 15083: }
! 15084: sqlite3_free(zTab);
! 15085: }
! 15086: return pTab;
! 15087: }
! 15088:
! 15089: /*
! 15090: ** This function is called to recover data from the database. A script
! 15091: ** to construct a new database containing all recovered data is output
! 15092: ** on stream pState->out.
! 15093: */
! 15094: static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
! 15095: int rc = SQLITE_OK;
! 15096: sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
! 15097: sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
! 15098: sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
! 15099: const char *zRecoveryDb = ""; /* Name of "recovery" database */
! 15100: const char *zLostAndFound = "lost_and_found";
! 15101: int i;
! 15102: int nOrphan = -1;
! 15103: RecoverTable *pOrphan = 0;
1.4.2.1 misho 15104:
1.4.2.2 ! misho 15105: int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
! 15106: for(i=1; i<nArg; i++){
! 15107: char *z = azArg[i];
! 15108: int n;
! 15109: if( z[0]=='-' && z[1]=='-' ) z++;
! 15110: n = strlen30(z);
! 15111: if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
! 15112: bFreelist = 0;
! 15113: }else
! 15114: if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
! 15115: i++;
! 15116: zRecoveryDb = azArg[i];
! 15117: }else
! 15118: if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
! 15119: i++;
! 15120: zLostAndFound = azArg[i];
1.4.2.1 misho 15121: }
15122: else{
1.4.2.2 ! misho 15123: raw_printf(stderr, "unexpected option: %s\n", azArg[i]);
! 15124: raw_printf(stderr, "options are:\n");
! 15125: raw_printf(stderr, " --freelist-corrupt\n");
! 15126: raw_printf(stderr, " --recovery-db DATABASE\n");
! 15127: raw_printf(stderr, " --lost-and-found TABLE-NAME\n");
! 15128: return 1;
1.4.2.1 misho 15129: }
15130: }
15131:
1.4.2.2 ! misho 15132: shellExecPrintf(pState->db, &rc,
! 15133: /* Attach an in-memory database named 'recovery'. Create an indexed
! 15134: ** cache of the sqlite_dbptr virtual table. */
! 15135: "ATTACH %Q AS recovery;"
! 15136: "DROP TABLE IF EXISTS recovery.dbptr;"
! 15137: "DROP TABLE IF EXISTS recovery.freelist;"
! 15138: "DROP TABLE IF EXISTS recovery.map;"
! 15139: "DROP TABLE IF EXISTS recovery.schema;"
! 15140: "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
! 15141: );
1.4.2.1 misho 15142:
1.4.2.2 ! misho 15143: if( bFreelist ){
! 15144: shellExec(pState->db, &rc,
! 15145: "WITH trunk(pgno) AS ("
! 15146: " SELECT shell_int32("
! 15147: " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
! 15148: " WHERE x>0"
! 15149: " UNION"
! 15150: " SELECT shell_int32("
! 15151: " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
! 15152: " FROM trunk WHERE x>0"
! 15153: "),"
! 15154: "freelist(data, n, freepgno) AS ("
! 15155: " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
! 15156: " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
! 15157: " UNION ALL"
! 15158: " SELECT data, n-1, shell_int32(data, 2+n) "
! 15159: " FROM freelist WHERE n>=0"
! 15160: ")"
! 15161: "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
! 15162: );
1.4.2.1 misho 15163: }
15164:
1.4.2.2 ! misho 15165: shellExec(pState->db, &rc,
! 15166: "CREATE TABLE recovery.dbptr("
! 15167: " pgno, child, PRIMARY KEY(child, pgno)"
! 15168: ") WITHOUT ROWID;"
! 15169: "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
! 15170: " SELECT * FROM sqlite_dbptr"
! 15171: " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
! 15172:
! 15173: /* Delete any pointer to page 1. This ensures that page 1 is considered
! 15174: ** a root page, regardless of how corrupt the db is. */
! 15175: "DELETE FROM recovery.dbptr WHERE child = 1;"
! 15176:
! 15177: /* Delete all pointers to any pages that have more than one pointer
! 15178: ** to them. Such pages will be treated as root pages when recovering
! 15179: ** data. */
! 15180: "DELETE FROM recovery.dbptr WHERE child IN ("
! 15181: " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
! 15182: ");"
! 15183:
! 15184: /* Create the "map" table that will (eventually) contain instructions
! 15185: ** for dealing with each page in the db that contains one or more
! 15186: ** records. */
! 15187: "CREATE TABLE recovery.map("
! 15188: "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
! 15189: ");"
! 15190:
! 15191: /* Populate table [map]. If there are circular loops of pages in the
! 15192: ** database, the following adds all pages in such a loop to the map
! 15193: ** as individual root pages. This could be handled better. */
! 15194: "WITH pages(i, maxlen) AS ("
! 15195: " SELECT page_count, ("
! 15196: " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
! 15197: " ) FROM pragma_page_count WHERE page_count>0"
! 15198: " UNION ALL"
! 15199: " SELECT i-1, ("
! 15200: " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
! 15201: " ) FROM pages WHERE i>=2"
! 15202: ")"
! 15203: "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
! 15204: " SELECT i, maxlen, NULL, ("
! 15205: " WITH p(orig, pgno, parent) AS ("
! 15206: " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
! 15207: " UNION "
! 15208: " SELECT i, p.parent, "
! 15209: " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
! 15210: " )"
! 15211: " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
! 15212: ") "
! 15213: "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
! 15214: "UPDATE recovery.map AS o SET intkey = ("
! 15215: " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
! 15216: ");"
! 15217:
! 15218: /* Extract data from page 1 and any linked pages into table
! 15219: ** recovery.schema. With the same schema as an sqlite_master table. */
! 15220: "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
! 15221: "INSERT INTO recovery.schema SELECT "
! 15222: " max(CASE WHEN field=0 THEN value ELSE NULL END),"
! 15223: " max(CASE WHEN field=1 THEN value ELSE NULL END),"
! 15224: " max(CASE WHEN field=2 THEN value ELSE NULL END),"
! 15225: " max(CASE WHEN field=3 THEN value ELSE NULL END),"
! 15226: " max(CASE WHEN field=4 THEN value ELSE NULL END)"
! 15227: "FROM sqlite_dbdata WHERE pgno IN ("
! 15228: " SELECT pgno FROM recovery.map WHERE root=1"
! 15229: ")"
! 15230: "GROUP BY pgno, cell;"
! 15231: "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
! 15232: );
! 15233:
! 15234: /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
! 15235: ** CREATE TABLE statements that extracted from the existing schema. */
1.4.2.1 misho 15236: if( rc==SQLITE_OK ){
1.4.2.2 ! misho 15237: sqlite3_stmt *pStmt = 0;
! 15238: raw_printf(pState->out, "BEGIN;\n");
! 15239: raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
! 15240: shellPrepare(pState->db, &rc,
! 15241: "SELECT sql FROM recovery.schema "
! 15242: "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
! 15243: );
! 15244: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 15245: const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
! 15246: raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
! 15247: &zCreateTable[12]
! 15248: );
! 15249: }
! 15250: shellFinalize(&rc, pStmt);
! 15251: }
1.4.2.1 misho 15252:
1.4.2.2 ! misho 15253: /* Figure out if an orphan table will be required. And if so, how many
! 15254: ** user columns it should contain */
! 15255: shellPrepare(pState->db, &rc,
! 15256: "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
! 15257: , &pLoop
! 15258: );
! 15259: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
! 15260: nOrphan = sqlite3_column_int(pLoop, 0);
! 15261: }
! 15262: shellFinalize(&rc, pLoop);
! 15263: pLoop = 0;
1.4.2.1 misho 15264:
1.4.2.2 ! misho 15265: shellPrepare(pState->db, &rc,
! 15266: "SELECT pgno FROM recovery.map WHERE root=?", &pPages
! 15267: );
! 15268: shellPrepare(pState->db, &rc,
! 15269: "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"
! 15270: "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
! 15271: "GROUP BY cell", &pCells
! 15272: );
1.4.2.1 misho 15273:
1.4.2.2 ! misho 15274: /* Loop through each root page. */
! 15275: shellPrepare(pState->db, &rc,
! 15276: "SELECT root, intkey, max(maxlen) FROM recovery.map"
! 15277: " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
! 15278: " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
! 15279: ")", &pLoop
! 15280: );
! 15281: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
! 15282: int iRoot = sqlite3_column_int(pLoop, 0);
! 15283: int bIntkey = sqlite3_column_int(pLoop, 1);
! 15284: int nCol = sqlite3_column_int(pLoop, 2);
! 15285: int bNoop = 0;
! 15286: RecoverTable *pTab;
! 15287:
! 15288: pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
! 15289: if( bNoop || rc ) continue;
! 15290: if( pTab==0 ){
! 15291: if( pOrphan==0 ){
! 15292: pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
! 15293: }
! 15294: pTab = pOrphan;
! 15295: if( pTab==0 ) break;
! 15296: }
! 15297:
! 15298: if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){
! 15299: raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
! 15300: }
! 15301: sqlite3_bind_int(pPages, 1, iRoot);
! 15302: sqlite3_bind_int(pCells, 2, pTab->iPk);
! 15303:
! 15304: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
! 15305: int iPgno = sqlite3_column_int(pPages, 0);
! 15306: sqlite3_bind_int(pCells, 1, iPgno);
! 15307: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
! 15308: int nField = sqlite3_column_int(pCells, 0);
! 15309: const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
! 15310:
! 15311: nField = nField+1;
! 15312: if( pTab==pOrphan ){
! 15313: raw_printf(pState->out,
! 15314: "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
! 15315: pTab->zQuoted, iRoot, iPgno, nField,
! 15316: bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]
! 15317: );
! 15318: }else{
! 15319: raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
! 15320: pTab->zQuoted, pTab->azlCol[nField], zVal
1.4.2.1 misho 15321: );
15322: }
15323: }
1.4.2.2 ! misho 15324: shellReset(&rc, pCells);
1.4.2.1 misho 15325: }
1.4.2.2 ! misho 15326: shellReset(&rc, pPages);
! 15327: if( pTab!=pOrphan ) recoverFreeTable(pTab);
! 15328: }
! 15329: shellFinalize(&rc, pLoop);
! 15330: shellFinalize(&rc, pPages);
! 15331: shellFinalize(&rc, pCells);
! 15332: recoverFreeTable(pOrphan);
1.4.2.1 misho 15333:
1.4.2.2 ! misho 15334: /* The rest of the schema */
! 15335: if( rc==SQLITE_OK ){
! 15336: sqlite3_stmt *pStmt = 0;
! 15337: shellPrepare(pState->db, &rc,
! 15338: "SELECT sql, name FROM recovery.schema "
! 15339: "WHERE sql NOT LIKE 'create table%'", &pStmt
! 15340: );
! 15341: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
! 15342: const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
! 15343: if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
! 15344: const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
! 15345: char *zPrint = shellMPrintf(&rc,
! 15346: "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",
! 15347: zName, zName, zSql
! 15348: );
! 15349: raw_printf(pState->out, "%s;\n", zPrint);
! 15350: sqlite3_free(zPrint);
! 15351: }else{
! 15352: raw_printf(pState->out, "%s;\n", zSql);
! 15353: }
1.4.2.1 misho 15354: }
1.4.2.2 ! misho 15355: shellFinalize(&rc, pStmt);
1.4.2.1 misho 15356: }
15357:
1.4.2.2 ! misho 15358: if( rc==SQLITE_OK ){
! 15359: raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
! 15360: raw_printf(pState->out, "COMMIT;\n");
! 15361: }
! 15362: sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
1.4.2.1 misho 15363: return rc;
15364: }
1.4.2.2 ! misho 15365: #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
1.4.2.1 misho 15366:
15367:
15368: /*
1.2 misho 15369: ** If an input line begins with "." then invoke this routine to
15370: ** process that line.
15371: **
15372: ** Return 1 on error, 2 to exit, and 0 otherwise.
15373: */
1.4 misho 15374: static int do_meta_command(char *zLine, ShellState *p){
15375: int h = 1;
1.2 misho 15376: int nArg = 0;
15377: int n, c;
15378: int rc = 0;
15379: char *azArg[50];
15380:
1.4.2.2 ! misho 15381: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 15382: if( p->expert.pExpert ){
! 15383: expertFinish(p, 1, 0);
! 15384: }
! 15385: #endif
! 15386:
1.2 misho 15387: /* Parse the input line into tokens.
15388: */
1.4 misho 15389: while( zLine[h] && nArg<ArraySize(azArg) ){
15390: while( IsSpace(zLine[h]) ){ h++; }
15391: if( zLine[h]==0 ) break;
15392: if( zLine[h]=='\'' || zLine[h]=='"' ){
15393: int delim = zLine[h++];
15394: azArg[nArg++] = &zLine[h];
15395: while( zLine[h] && zLine[h]!=delim ){
15396: if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
15397: h++;
15398: }
15399: if( zLine[h]==delim ){
15400: zLine[h++] = 0;
1.2 misho 15401: }
15402: if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
15403: }else{
1.4 misho 15404: azArg[nArg++] = &zLine[h];
15405: while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
15406: if( zLine[h] ) zLine[h++] = 0;
1.2 misho 15407: resolve_backslashes(azArg[nArg-1]);
15408: }
15409: }
15410:
15411: /* Process the input line.
15412: */
15413: if( nArg==0 ) return 0; /* no tokens, no error */
15414: n = strlen30(azArg[0]);
15415: c = azArg[0][0];
1.4.2.2 ! misho 15416: clearTempFile(p);
1.4 misho 15417:
1.4.2.1 misho 15418: #ifndef SQLITE_OMIT_AUTHORIZATION
1.4 misho 15419: if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
15420: if( nArg!=2 ){
15421: raw_printf(stderr, "Usage: .auth ON|OFF\n");
15422: rc = 1;
15423: goto meta_command_exit;
15424: }
15425: open_db(p, 0);
15426: if( booleanValue(azArg[1]) ){
15427: sqlite3_set_authorizer(p->db, shellAuth, p);
15428: }else{
15429: sqlite3_set_authorizer(p->db, 0, 0);
15430: }
15431: }else
1.4.2.1 misho 15432: #endif
1.4 misho 15433:
1.4.2.2 ! misho 15434: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
! 15435: if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
! 15436: open_db(p, 0);
! 15437: rc = arDotCommand(p, 0, azArg, nArg);
! 15438: }else
! 15439: #endif
! 15440:
1.4 misho 15441: if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
15442: || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
15443: ){
15444: const char *zDestFile = 0;
15445: const char *zDb = 0;
1.2 misho 15446: sqlite3 *pDest;
15447: sqlite3_backup *pBackup;
1.4 misho 15448: int j;
1.4.2.2 ! misho 15449: int bAsync = 0;
! 15450: const char *zVfs = 0;
1.4 misho 15451: for(j=1; j<nArg; j++){
15452: const char *z = azArg[j];
15453: if( z[0]=='-' ){
1.4.2.2 ! misho 15454: if( z[1]=='-' ) z++;
! 15455: if( strcmp(z, "-append")==0 ){
! 15456: zVfs = "apndvfs";
! 15457: }else
! 15458: if( strcmp(z, "-async")==0 ){
! 15459: bAsync = 1;
! 15460: }else
1.4 misho 15461: {
15462: utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
15463: return 1;
15464: }
15465: }else if( zDestFile==0 ){
15466: zDestFile = azArg[j];
15467: }else if( zDb==0 ){
15468: zDb = zDestFile;
15469: zDestFile = azArg[j];
15470: }else{
1.4.2.2 ! misho 15471: raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
1.4 misho 15472: return 1;
15473: }
15474: }
15475: if( zDestFile==0 ){
15476: raw_printf(stderr, "missing FILENAME argument on .backup\n");
15477: return 1;
1.2 misho 15478: }
1.4 misho 15479: if( zDb==0 ) zDb = "main";
1.4.2.2 ! misho 15480: rc = sqlite3_open_v2(zDestFile, &pDest,
! 15481: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
1.2 misho 15482: if( rc!=SQLITE_OK ){
1.4 misho 15483: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
1.4.2.2 ! misho 15484: close_db(pDest);
1.2 misho 15485: return 1;
15486: }
1.4.2.2 ! misho 15487: if( bAsync ){
! 15488: sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
! 15489: 0, 0, 0);
! 15490: }
1.4 misho 15491: open_db(p, 0);
1.2 misho 15492: pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
15493: if( pBackup==0 ){
1.4 misho 15494: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
1.4.2.2 ! misho 15495: close_db(pDest);
1.2 misho 15496: return 1;
15497: }
15498: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
15499: sqlite3_backup_finish(pBackup);
15500: if( rc==SQLITE_DONE ){
15501: rc = 0;
15502: }else{
1.4 misho 15503: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
1.2 misho 15504: rc = 1;
15505: }
1.4.2.2 ! misho 15506: close_db(pDest);
1.2 misho 15507: }else
15508:
1.4 misho 15509: if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
15510: if( nArg==2 ){
15511: bail_on_error = booleanValue(azArg[1]);
15512: }else{
15513: raw_printf(stderr, "Usage: .bail on|off\n");
15514: rc = 1;
15515: }
15516: }else
15517:
15518: if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
15519: if( nArg==2 ){
15520: if( booleanValue(azArg[1]) ){
15521: setBinaryMode(p->out, 1);
15522: }else{
15523: setTextMode(p->out, 1);
15524: }
15525: }else{
15526: raw_printf(stderr, "Usage: .binary on|off\n");
15527: rc = 1;
15528: }
1.2 misho 15529: }else
15530:
1.4.2.2 ! misho 15531: if( c=='c' && strcmp(azArg[0],"cd")==0 ){
! 15532: if( nArg==2 ){
! 15533: #if defined(_WIN32) || defined(WIN32)
! 15534: wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
! 15535: rc = !SetCurrentDirectoryW(z);
! 15536: sqlite3_free(z);
! 15537: #else
! 15538: rc = chdir(azArg[1]);
! 15539: #endif
! 15540: if( rc ){
! 15541: utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
! 15542: rc = 1;
! 15543: }
! 15544: }else{
! 15545: raw_printf(stderr, "Usage: .cd DIRECTORY\n");
! 15546: rc = 1;
! 15547: }
! 15548: }else
! 15549:
1.3 misho 15550: /* The undocumented ".breakpoint" command causes a call to the no-op
15551: ** routine named test_breakpoint().
15552: */
15553: if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
15554: test_breakpoint();
15555: }else
15556:
1.4 misho 15557: if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
15558: if( nArg==2 ){
1.4.2.1 misho 15559: setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
1.4 misho 15560: }else{
15561: raw_printf(stderr, "Usage: .changes on|off\n");
15562: rc = 1;
15563: }
15564: }else
15565:
1.4.2.1 misho 15566: /* Cancel output redirection, if it is currently set (by .testcase)
15567: ** Then read the content of the testcase-out.txt file and compare against
15568: ** azArg[1]. If there are differences, report an error and exit.
15569: */
15570: if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
15571: char *zRes = 0;
15572: output_reset(p);
15573: if( nArg!=2 ){
15574: raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
15575: rc = 2;
15576: }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
15577: raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
15578: rc = 2;
15579: }else if( testcase_glob(azArg[1],zRes)==0 ){
15580: utf8_printf(stderr,
15581: "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
15582: p->zTestcase, azArg[1], zRes);
1.4.2.2 ! misho 15583: rc = 1;
1.4.2.1 misho 15584: }else{
15585: utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
15586: p->nCheck++;
15587: }
15588: sqlite3_free(zRes);
15589: }else
15590:
1.4 misho 15591: if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
15592: if( nArg==2 ){
15593: tryToClone(p, azArg[1]);
15594: }else{
15595: raw_printf(stderr, "Usage: .clone FILENAME\n");
15596: rc = 1;
15597: }
15598: }else
15599:
15600: if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
15601: ShellState data;
1.2 misho 15602: char *zErrMsg = 0;
1.4 misho 15603: open_db(p, 0);
1.2 misho 15604: memcpy(&data, p, sizeof(data));
1.4.2.1 misho 15605: data.showHeader = 0;
15606: data.cMode = data.mode = MODE_List;
15607: sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
1.2 misho 15608: data.cnt = 0;
1.4.2.1 misho 15609: sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
15610: callback, &data, &zErrMsg);
1.2 misho 15611: if( zErrMsg ){
1.4 misho 15612: utf8_printf(stderr,"Error: %s\n", zErrMsg);
1.2 misho 15613: sqlite3_free(zErrMsg);
15614: rc = 1;
15615: }
15616: }else
15617:
1.4.2.2 ! misho 15618: if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
! 15619: static const struct DbConfigChoices {
! 15620: const char *zName;
! 15621: int op;
! 15622: } aDbConfig[] = {
! 15623: { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
! 15624: { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
! 15625: { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
! 15626: { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
! 15627: { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
! 15628: { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
! 15629: { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
! 15630: { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
! 15631: { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
! 15632: { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
! 15633: { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
! 15634: { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
! 15635: { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
! 15636: };
! 15637: int ii, v;
! 15638: open_db(p, 0);
! 15639: for(ii=0; ii<ArraySize(aDbConfig); ii++){
! 15640: if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
! 15641: if( nArg>=3 ){
! 15642: sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
! 15643: }
! 15644: sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
! 15645: utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
! 15646: if( nArg>1 ) break;
! 15647: }
! 15648: if( nArg>1 && ii==ArraySize(aDbConfig) ){
! 15649: utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
! 15650: utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
! 15651: }
! 15652: }else
! 15653:
! 15654: if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
1.4 misho 15655: rc = shell_dbinfo_command(p, nArg, azArg);
15656: }else
15657:
1.4.2.2 ! misho 15658: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 15659: if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
! 15660: open_db(p, 0);
! 15661: rc = recoverDatabaseCmd(p, nArg, azArg);
! 15662: }else
! 15663: #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
! 15664:
1.4 misho 15665: if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
1.4.2.1 misho 15666: const char *zLike = 0;
15667: int i;
15668: int savedShowHeader = p->showHeader;
1.4.2.2 ! misho 15669: int savedShellFlags = p->shellFlgs;
! 15670: ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
1.4.2.1 misho 15671: for(i=1; i<nArg; i++){
15672: if( azArg[i][0]=='-' ){
15673: const char *z = azArg[i]+1;
15674: if( z[0]=='-' ) z++;
15675: if( strcmp(z,"preserve-rowids")==0 ){
15676: #ifdef SQLITE_OMIT_VIRTUALTABLE
15677: raw_printf(stderr, "The --preserve-rowids option is not compatible"
15678: " with SQLITE_OMIT_VIRTUALTABLE\n");
15679: rc = 1;
15680: goto meta_command_exit;
15681: #else
15682: ShellSetFlag(p, SHFLG_PreserveRowid);
15683: #endif
15684: }else
1.4.2.2 ! misho 15685: if( strcmp(z,"newlines")==0 ){
! 15686: ShellSetFlag(p, SHFLG_Newlines);
! 15687: }else
1.4.2.1 misho 15688: {
15689: raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
15690: rc = 1;
15691: goto meta_command_exit;
15692: }
15693: }else if( zLike ){
1.4.2.2 ! misho 15694: raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
! 15695: "?--newlines? ?LIKE-PATTERN?\n");
1.4.2.1 misho 15696: rc = 1;
15697: goto meta_command_exit;
15698: }else{
15699: zLike = azArg[i];
15700: }
15701: }
1.4.2.2 ! misho 15702:
1.4 misho 15703: open_db(p, 0);
1.4.2.2 ! misho 15704:
1.2 misho 15705: /* When playing back a "dump", the content might appear in an order
15706: ** which causes immediate foreign key constraints to be violated.
15707: ** So disable foreign-key constraint enforcement to prevent problems. */
1.4 misho 15708: raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
15709: raw_printf(p->out, "BEGIN TRANSACTION;\n");
1.2 misho 15710: p->writableSchema = 0;
1.4.2.1 misho 15711: p->showHeader = 0;
15712: /* Set writable_schema=ON since doing so forces SQLite to initialize
15713: ** as much of the schema as it can even if the sqlite_master table is
15714: ** corrupt. */
1.2 misho 15715: sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
15716: p->nErr = 0;
1.4.2.1 misho 15717: if( zLike==0 ){
1.4 misho 15718: run_schema_dump_query(p,
1.2 misho 15719: "SELECT name, type, sql FROM sqlite_master "
15720: "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
15721: );
1.4 misho 15722: run_schema_dump_query(p,
1.2 misho 15723: "SELECT name, type, sql FROM sqlite_master "
15724: "WHERE name=='sqlite_sequence'"
15725: );
15726: run_table_dump_query(p,
15727: "SELECT sql FROM sqlite_master "
15728: "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
15729: );
15730: }else{
1.4.2.1 misho 15731: char *zSql;
15732: zSql = sqlite3_mprintf(
15733: "SELECT name, type, sql FROM sqlite_master "
15734: "WHERE tbl_name LIKE %Q AND type=='table'"
15735: " AND sql NOT NULL", zLike);
15736: run_schema_dump_query(p,zSql);
15737: sqlite3_free(zSql);
15738: zSql = sqlite3_mprintf(
15739: "SELECT sql FROM sqlite_master "
15740: "WHERE sql NOT NULL"
15741: " AND type IN ('index','trigger','view')"
15742: " AND tbl_name LIKE %Q", zLike);
15743: run_table_dump_query(p, zSql, 0);
15744: sqlite3_free(zSql);
1.2 misho 15745: }
15746: if( p->writableSchema ){
1.4 misho 15747: raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
1.2 misho 15748: p->writableSchema = 0;
15749: }
15750: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
15751: sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
1.4.2.2 ! misho 15752: raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
1.4.2.1 misho 15753: p->showHeader = savedShowHeader;
1.4.2.2 ! misho 15754: p->shellFlgs = savedShellFlags;
1.4 misho 15755: }else
15756:
15757: if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
15758: if( nArg==2 ){
1.4.2.1 misho 15759: setOrClearFlag(p, SHFLG_Echo, azArg[1]);
1.4 misho 15760: }else{
15761: raw_printf(stderr, "Usage: .echo on|off\n");
15762: rc = 1;
15763: }
1.2 misho 15764: }else
15765:
1.4 misho 15766: if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
15767: if( nArg==2 ){
1.4.2.2 ! misho 15768: p->autoEQPtest = 0;
! 15769: if( p->autoEQPtrace ){
! 15770: if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
! 15771: p->autoEQPtrace = 0;
! 15772: }
1.4 misho 15773: if( strcmp(azArg[1],"full")==0 ){
1.4.2.2 ! misho 15774: p->autoEQP = AUTOEQP_full;
! 15775: }else if( strcmp(azArg[1],"trigger")==0 ){
! 15776: p->autoEQP = AUTOEQP_trigger;
! 15777: #ifdef SQLITE_DEBUG
! 15778: }else if( strcmp(azArg[1],"test")==0 ){
! 15779: p->autoEQP = AUTOEQP_on;
! 15780: p->autoEQPtest = 1;
! 15781: }else if( strcmp(azArg[1],"trace")==0 ){
! 15782: p->autoEQP = AUTOEQP_full;
! 15783: p->autoEQPtrace = 1;
! 15784: open_db(p, 0);
! 15785: sqlite3_exec(p->db, "SELECT name FROM sqlite_master LIMIT 1", 0, 0, 0);
! 15786: sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
! 15787: #endif
1.4 misho 15788: }else{
1.4.2.2 ! misho 15789: p->autoEQP = (u8)booleanValue(azArg[1]);
1.4 misho 15790: }
15791: }else{
1.4.2.2 ! misho 15792: raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
1.4 misho 15793: rc = 1;
15794: }
1.2 misho 15795: }else
15796:
1.4 misho 15797: if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
15798: if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
1.2 misho 15799: rc = 2;
15800: }else
15801:
1.4.2.2 ! misho 15802: /* The ".explain" command is automatic now. It is largely pointless. It
! 15803: ** retained purely for backwards compatibility */
1.4 misho 15804: if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
15805: int val = 1;
15806: if( nArg>=2 ){
15807: if( strcmp(azArg[1],"auto")==0 ){
15808: val = 99;
15809: }else{
15810: val = booleanValue(azArg[1]);
15811: }
15812: }
15813: if( val==1 && p->mode!=MODE_Explain ){
15814: p->normalMode = p->mode;
1.2 misho 15815: p->mode = MODE_Explain;
1.4 misho 15816: p->autoExplain = 0;
15817: }else if( val==0 ){
15818: if( p->mode==MODE_Explain ) p->mode = p->normalMode;
15819: p->autoExplain = 0;
15820: }else if( val==99 ){
15821: if( p->mode==MODE_Explain ) p->mode = p->normalMode;
15822: p->autoExplain = 1;
15823: }
15824: }else
15825:
1.4.2.2 ! misho 15826: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 15827: if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
! 15828: open_db(p, 0);
! 15829: expertDotCommand(p, azArg, nArg);
! 15830: }else
! 15831: #endif
! 15832:
! 15833: if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
! 15834: static const struct {
! 15835: const char *zCtrlName; /* Name of a test-control option */
! 15836: int ctrlCode; /* Integer code for that option */
! 15837: const char *zUsage; /* Usage notes */
! 15838: } aCtrl[] = {
! 15839: { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
! 15840: { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
! 15841: /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
! 15842: { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
! 15843: { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
! 15844: /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
! 15845: { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
! 15846: { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
! 15847: { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
! 15848: };
! 15849: int filectrl = -1;
! 15850: int iCtrl = -1;
! 15851: sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
! 15852: int isOk = 0; /* 0: usage 1: %lld 2: no-result */
! 15853: int n2, i;
! 15854: const char *zCmd = 0;
! 15855:
! 15856: open_db(p, 0);
! 15857: zCmd = nArg>=2 ? azArg[1] : "help";
! 15858:
! 15859: /* The argument can optionally begin with "-" or "--" */
! 15860: if( zCmd[0]=='-' && zCmd[1] ){
! 15861: zCmd++;
! 15862: if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
! 15863: }
! 15864:
! 15865: /* --help lists all file-controls */
! 15866: if( strcmp(zCmd,"help")==0 ){
! 15867: utf8_printf(p->out, "Available file-controls:\n");
! 15868: for(i=0; i<ArraySize(aCtrl); i++){
! 15869: utf8_printf(p->out, " .filectrl %s %s\n",
! 15870: aCtrl[i].zCtrlName, aCtrl[i].zUsage);
! 15871: }
! 15872: rc = 1;
! 15873: goto meta_command_exit;
! 15874: }
! 15875:
! 15876: /* convert filectrl text option to value. allow any unique prefix
! 15877: ** of the option name, or a numerical value. */
! 15878: n2 = strlen30(zCmd);
! 15879: for(i=0; i<ArraySize(aCtrl); i++){
! 15880: if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
! 15881: if( filectrl<0 ){
! 15882: filectrl = aCtrl[i].ctrlCode;
! 15883: iCtrl = i;
! 15884: }else{
! 15885: utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
! 15886: "Use \".filectrl --help\" for help\n", zCmd);
! 15887: rc = 1;
! 15888: goto meta_command_exit;
! 15889: }
! 15890: }
! 15891: }
! 15892: if( filectrl<0 ){
! 15893: utf8_printf(stderr,"Error: unknown file-control: %s\n"
! 15894: "Use \".filectrl --help\" for help\n", zCmd);
! 15895: }else{
! 15896: switch(filectrl){
! 15897: case SQLITE_FCNTL_SIZE_LIMIT: {
! 15898: if( nArg!=2 && nArg!=3 ) break;
! 15899: iRes = nArg==3 ? integerValue(azArg[2]) : -1;
! 15900: sqlite3_file_control(p->db, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
! 15901: isOk = 1;
! 15902: break;
! 15903: }
! 15904: case SQLITE_FCNTL_LOCK_TIMEOUT:
! 15905: case SQLITE_FCNTL_CHUNK_SIZE: {
! 15906: int x;
! 15907: if( nArg!=3 ) break;
! 15908: x = (int)integerValue(azArg[2]);
! 15909: sqlite3_file_control(p->db, 0, filectrl, &x);
! 15910: isOk = 2;
! 15911: break;
! 15912: }
! 15913: case SQLITE_FCNTL_PERSIST_WAL:
! 15914: case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
! 15915: int x;
! 15916: if( nArg!=2 && nArg!=3 ) break;
! 15917: x = nArg==3 ? booleanValue(azArg[2]) : -1;
! 15918: sqlite3_file_control(p->db, 0, filectrl, &x);
! 15919: iRes = x;
! 15920: isOk = 1;
! 15921: break;
! 15922: }
! 15923: case SQLITE_FCNTL_HAS_MOVED: {
! 15924: int x;
! 15925: if( nArg!=2 ) break;
! 15926: sqlite3_file_control(p->db, 0, filectrl, &x);
! 15927: iRes = x;
! 15928: isOk = 1;
! 15929: break;
! 15930: }
! 15931: case SQLITE_FCNTL_TEMPFILENAME: {
! 15932: char *z = 0;
! 15933: if( nArg!=2 ) break;
! 15934: sqlite3_file_control(p->db, 0, filectrl, &z);
! 15935: if( z ){
! 15936: utf8_printf(p->out, "%s\n", z);
! 15937: sqlite3_free(z);
! 15938: }
! 15939: isOk = 2;
! 15940: break;
! 15941: }
! 15942: }
! 15943: }
! 15944: if( isOk==0 && iCtrl>=0 ){
! 15945: utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
! 15946: rc = 1;
! 15947: }else if( isOk==1 ){
! 15948: char zBuf[100];
! 15949: sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
! 15950: raw_printf(p->out, "%s\n", zBuf);
! 15951: }
! 15952: }else
! 15953:
1.4 misho 15954: if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
15955: ShellState data;
15956: char *zErrMsg = 0;
15957: int doStats = 0;
15958: memcpy(&data, p, sizeof(data));
15959: data.showHeader = 0;
15960: data.cMode = data.mode = MODE_Semi;
15961: if( nArg==2 && optionMatch(azArg[1], "indent") ){
15962: data.cMode = data.mode = MODE_Pretty;
15963: nArg = 1;
15964: }
15965: if( nArg!=1 ){
15966: raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
15967: rc = 1;
15968: goto meta_command_exit;
15969: }
15970: open_db(p, 0);
15971: rc = sqlite3_exec(p->db,
15972: "SELECT sql FROM"
15973: " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
15974: " FROM sqlite_master UNION ALL"
15975: " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
15976: "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
15977: "ORDER BY rowid",
15978: callback, &data, &zErrMsg
15979: );
15980: if( rc==SQLITE_OK ){
15981: sqlite3_stmt *pStmt;
15982: rc = sqlite3_prepare_v2(p->db,
15983: "SELECT rowid FROM sqlite_master"
15984: " WHERE name GLOB 'sqlite_stat[134]'",
15985: -1, &pStmt, 0);
15986: doStats = sqlite3_step(pStmt)==SQLITE_ROW;
15987: sqlite3_finalize(pStmt);
15988: }
15989: if( doStats==0 ){
15990: raw_printf(p->out, "/* No STAT tables available */\n");
15991: }else{
15992: raw_printf(p->out, "ANALYZE sqlite_master;\n");
15993: sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
15994: callback, &data, &zErrMsg);
15995: data.cMode = data.mode = MODE_Insert;
15996: data.zDestTable = "sqlite_stat1";
1.4.2.2 ! misho 15997: shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
1.4 misho 15998: data.zDestTable = "sqlite_stat3";
1.4.2.2 ! misho 15999: shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);
1.4 misho 16000: data.zDestTable = "sqlite_stat4";
1.4.2.2 ! misho 16001: shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
1.4 misho 16002: raw_printf(p->out, "ANALYZE sqlite_master;\n");
1.2 misho 16003: }
16004: }else
16005:
1.4 misho 16006: if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
16007: if( nArg==2 ){
16008: p->showHeader = booleanValue(azArg[1]);
16009: }else{
16010: raw_printf(stderr, "Usage: .headers on|off\n");
16011: rc = 1;
16012: }
1.2 misho 16013: }else
16014:
16015: if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
1.4.2.2 ! misho 16016: if( nArg>=2 ){
! 16017: n = showHelp(p->out, azArg[1]);
! 16018: if( n==0 ){
! 16019: utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
! 16020: }
! 16021: }else{
! 16022: showHelp(p->out, 0);
! 16023: }
1.2 misho 16024: }else
16025:
1.4 misho 16026: if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
16027: char *zTable; /* Insert data into this table */
16028: char *zFile; /* Name of file to extra content from */
1.2 misho 16029: sqlite3_stmt *pStmt = NULL; /* A statement */
16030: int nCol; /* Number of columns in the table */
16031: int nByte; /* Number of bytes in an SQL string */
16032: int i, j; /* Loop counters */
1.4 misho 16033: int needCommit; /* True to COMMIT or ROLLBACK at end */
16034: int nSep; /* Number of bytes in p->colSeparator[] */
1.2 misho 16035: char *zSql; /* An SQL statement */
1.4 misho 16036: ImportCtx sCtx; /* Reader context */
16037: char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
16038: int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
16039:
16040: if( nArg!=3 ){
16041: raw_printf(stderr, "Usage: .import FILE TABLE\n");
16042: goto meta_command_exit;
16043: }
16044: zFile = azArg[1];
16045: zTable = azArg[2];
16046: seenInterrupt = 0;
16047: memset(&sCtx, 0, sizeof(sCtx));
16048: open_db(p, 0);
16049: nSep = strlen30(p->colSeparator);
16050: if( nSep==0 ){
16051: raw_printf(stderr,
16052: "Error: non-null column separator required for import\n");
16053: return 1;
16054: }
16055: if( nSep>1 ){
16056: raw_printf(stderr, "Error: multi-character column separators not allowed"
16057: " for import\n");
16058: return 1;
16059: }
16060: nSep = strlen30(p->rowSeparator);
1.2 misho 16061: if( nSep==0 ){
1.4 misho 16062: raw_printf(stderr, "Error: non-null row separator required for import\n");
1.2 misho 16063: return 1;
16064: }
1.4 misho 16065: if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
16066: /* When importing CSV (only), if the row separator is set to the
16067: ** default output row separator, change it to the default input
16068: ** row separator. This avoids having to maintain different input
16069: ** and output row separators. */
16070: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
16071: nSep = strlen30(p->rowSeparator);
16072: }
16073: if( nSep>1 ){
16074: raw_printf(stderr, "Error: multi-character row separators not allowed"
16075: " for import\n");
16076: return 1;
16077: }
16078: sCtx.zFile = zFile;
16079: sCtx.nLine = 1;
16080: if( sCtx.zFile[0]=='|' ){
16081: #ifdef SQLITE_OMIT_POPEN
16082: raw_printf(stderr, "Error: pipes are not supported in this OS\n");
16083: return 1;
16084: #else
16085: sCtx.in = popen(sCtx.zFile+1, "r");
16086: sCtx.zFile = "<pipe>";
16087: xCloser = pclose;
16088: #endif
16089: }else{
16090: sCtx.in = fopen(sCtx.zFile, "rb");
16091: xCloser = fclose;
16092: }
16093: if( p->mode==MODE_Ascii ){
16094: xRead = ascii_read_one_field;
16095: }else{
16096: xRead = csv_read_one_field;
16097: }
16098: if( sCtx.in==0 ){
16099: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
16100: return 1;
16101: }
16102: sCtx.cColSep = p->colSeparator[0];
16103: sCtx.cRowSep = p->rowSeparator[0];
1.2 misho 16104: zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
16105: if( zSql==0 ){
1.4 misho 16106: xCloser(sCtx.in);
1.4.2.2 ! misho 16107: shell_out_of_memory();
1.2 misho 16108: }
16109: nByte = strlen30(zSql);
1.4 misho 16110: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16111: import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
16112: if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
16113: char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
16114: char cSep = '(';
16115: while( xRead(&sCtx) ){
16116: zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
16117: cSep = ',';
16118: if( sCtx.cTerm!=sCtx.cColSep ) break;
16119: }
16120: if( cSep=='(' ){
16121: sqlite3_free(zCreate);
16122: sqlite3_free(sCtx.z);
16123: xCloser(sCtx.in);
16124: utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
16125: return 1;
16126: }
16127: zCreate = sqlite3_mprintf("%z\n)", zCreate);
16128: rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
16129: sqlite3_free(zCreate);
16130: if( rc ){
16131: utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
16132: sqlite3_errmsg(p->db));
16133: sqlite3_free(sCtx.z);
16134: xCloser(sCtx.in);
16135: return 1;
16136: }
16137: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16138: }
1.2 misho 16139: sqlite3_free(zSql);
16140: if( rc ){
16141: if (pStmt) sqlite3_finalize(pStmt);
1.4 misho 16142: utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
16143: xCloser(sCtx.in);
1.2 misho 16144: return 1;
16145: }
16146: nCol = sqlite3_column_count(pStmt);
16147: sqlite3_finalize(pStmt);
16148: pStmt = 0;
16149: if( nCol==0 ) return 0; /* no columns, no error */
1.4 misho 16150: zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
1.2 misho 16151: if( zSql==0 ){
1.4 misho 16152: xCloser(sCtx.in);
1.4.2.2 ! misho 16153: shell_out_of_memory();
1.2 misho 16154: }
1.4 misho 16155: sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
1.2 misho 16156: j = strlen30(zSql);
16157: for(i=1; i<nCol; i++){
16158: zSql[j++] = ',';
16159: zSql[j++] = '?';
16160: }
16161: zSql[j++] = ')';
16162: zSql[j] = 0;
1.4 misho 16163: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16164: sqlite3_free(zSql);
1.2 misho 16165: if( rc ){
1.4 misho 16166: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 16167: if (pStmt) sqlite3_finalize(pStmt);
1.4 misho 16168: xCloser(sCtx.in);
1.2 misho 16169: return 1;
16170: }
1.4 misho 16171: needCommit = sqlite3_get_autocommit(p->db);
16172: if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
16173: do{
16174: int startLine = sCtx.nLine;
16175: for(i=0; i<nCol; i++){
16176: char *z = xRead(&sCtx);
16177: /*
16178: ** Did we reach end-of-file before finding any columns?
16179: ** If so, stop instead of NULL filling the remaining columns.
16180: */
16181: if( z==0 && i==0 ) break;
16182: /*
16183: ** Did we reach end-of-file OR end-of-line before finding any
16184: ** columns in ASCII mode? If so, stop instead of NULL filling
16185: ** the remaining columns.
16186: */
16187: if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
16188: sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
16189: if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
16190: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
16191: "filling the rest with NULL\n",
16192: sCtx.zFile, startLine, nCol, i+1);
16193: i += 2;
16194: while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
16195: }
16196: }
16197: if( sCtx.cTerm==sCtx.cColSep ){
16198: do{
16199: xRead(&sCtx);
1.2 misho 16200: i++;
1.4 misho 16201: }while( sCtx.cTerm==sCtx.cColSep );
16202: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
16203: "extras ignored\n",
16204: sCtx.zFile, startLine, nCol, i);
16205: }
16206: if( i>=nCol ){
16207: sqlite3_step(pStmt);
16208: rc = sqlite3_reset(pStmt);
16209: if( rc!=SQLITE_OK ){
16210: utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
16211: startLine, sqlite3_errmsg(p->db));
1.2 misho 16212: }
16213: }
1.4 misho 16214: }while( sCtx.cTerm!=EOF );
16215:
16216: xCloser(sCtx.in);
16217: sqlite3_free(sCtx.z);
1.2 misho 16218: sqlite3_finalize(pStmt);
1.4 misho 16219: if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
1.2 misho 16220: }else
16221:
1.4.2.1 misho 16222: #ifndef SQLITE_UNTESTABLE
16223: if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
16224: char *zSql;
16225: char *zCollist = 0;
16226: sqlite3_stmt *pStmt;
16227: int tnum = 0;
16228: int i;
1.4.2.2 ! misho 16229: if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
! 16230: utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
! 16231: " .imposter off\n");
1.4 misho 16232: rc = 1;
16233: goto meta_command_exit;
1.2 misho 16234: }
1.4.2.1 misho 16235: open_db(p, 0);
1.4.2.2 ! misho 16236: if( nArg==2 ){
! 16237: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
! 16238: goto meta_command_exit;
! 16239: }
1.4.2.1 misho 16240: zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
16241: " WHERE name='%q' AND type='index'", azArg[1]);
16242: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16243: sqlite3_free(zSql);
16244: if( sqlite3_step(pStmt)==SQLITE_ROW ){
16245: tnum = sqlite3_column_int(pStmt, 0);
16246: }
16247: sqlite3_finalize(pStmt);
16248: if( tnum==0 ){
16249: utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
1.2 misho 16250: rc = 1;
1.4.2.1 misho 16251: goto meta_command_exit;
16252: }
16253: zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
16254: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16255: sqlite3_free(zSql);
16256: i = 0;
16257: while( sqlite3_step(pStmt)==SQLITE_ROW ){
16258: char zLabel[20];
16259: const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
16260: i++;
16261: if( zCol==0 ){
16262: if( sqlite3_column_int(pStmt,1)==-1 ){
16263: zCol = "_ROWID_";
16264: }else{
16265: sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
16266: zCol = zLabel;
16267: }
16268: }
16269: if( zCollist==0 ){
16270: zCollist = sqlite3_mprintf("\"%w\"", zCol);
16271: }else{
16272: zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
16273: }
16274: }
16275: sqlite3_finalize(pStmt);
16276: zSql = sqlite3_mprintf(
16277: "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
16278: azArg[2], zCollist, zCollist);
16279: sqlite3_free(zCollist);
16280: rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
16281: if( rc==SQLITE_OK ){
16282: rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
16283: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
16284: if( rc ){
16285: utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
16286: }else{
16287: utf8_printf(stdout, "%s;\n", zSql);
16288: raw_printf(stdout,
16289: "WARNING: writing to an imposter table will corrupt the index!\n"
16290: );
16291: }
16292: }else{
16293: raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
1.2 misho 16294: rc = 1;
16295: }
1.4.2.1 misho 16296: sqlite3_free(zSql);
1.2 misho 16297: }else
1.4.2.1 misho 16298: #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
1.2 misho 16299:
16300: #ifdef SQLITE_ENABLE_IOTRACE
16301: if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
1.4 misho 16302: SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
1.2 misho 16303: if( iotrace && iotrace!=stdout ) fclose(iotrace);
16304: iotrace = 0;
16305: if( nArg<2 ){
16306: sqlite3IoTrace = 0;
16307: }else if( strcmp(azArg[1], "-")==0 ){
16308: sqlite3IoTrace = iotracePrintf;
16309: iotrace = stdout;
1.4 misho 16310: }else{
16311: iotrace = fopen(azArg[1], "w");
16312: if( iotrace==0 ){
16313: utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
16314: sqlite3IoTrace = 0;
16315: rc = 1;
16316: }else{
16317: sqlite3IoTrace = iotracePrintf;
16318: }
16319: }
16320: }else
16321: #endif
1.4.2.1 misho 16322:
1.4 misho 16323: if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
16324: static const struct {
16325: const char *zLimitName; /* Name of a limit */
16326: int limitCode; /* Integer code for that limit */
16327: } aLimit[] = {
16328: { "length", SQLITE_LIMIT_LENGTH },
16329: { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
16330: { "column", SQLITE_LIMIT_COLUMN },
16331: { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
16332: { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
16333: { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
16334: { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
16335: { "attached", SQLITE_LIMIT_ATTACHED },
16336: { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
16337: { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
16338: { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
16339: { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
16340: };
16341: int i, n2;
16342: open_db(p, 0);
16343: if( nArg==1 ){
16344: for(i=0; i<ArraySize(aLimit); i++){
16345: printf("%20s %d\n", aLimit[i].zLimitName,
16346: sqlite3_limit(p->db, aLimit[i].limitCode, -1));
16347: }
16348: }else if( nArg>3 ){
16349: raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
16350: rc = 1;
16351: goto meta_command_exit;
16352: }else{
16353: int iLimit = -1;
16354: n2 = strlen30(azArg[1]);
16355: for(i=0; i<ArraySize(aLimit); i++){
16356: if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
16357: if( iLimit<0 ){
16358: iLimit = i;
16359: }else{
16360: utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
16361: rc = 1;
16362: goto meta_command_exit;
16363: }
16364: }
16365: }
16366: if( iLimit<0 ){
16367: utf8_printf(stderr, "unknown limit: \"%s\"\n"
16368: "enter \".limits\" with no arguments for a list.\n",
16369: azArg[1]);
1.2 misho 16370: rc = 1;
1.4 misho 16371: goto meta_command_exit;
16372: }
16373: if( nArg==3 ){
16374: sqlite3_limit(p->db, aLimit[iLimit].limitCode,
16375: (int)integerValue(azArg[2]));
1.2 misho 16376: }
1.4 misho 16377: printf("%20s %d\n", aLimit[iLimit].zLimitName,
16378: sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
1.2 misho 16379: }
16380: }else
16381:
1.4.2.1 misho 16382: if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
16383: open_db(p, 0);
16384: lintDotCommand(p, azArg, nArg);
16385: }else
16386:
1.2 misho 16387: #ifndef SQLITE_OMIT_LOAD_EXTENSION
1.4 misho 16388: if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
1.2 misho 16389: const char *zFile, *zProc;
16390: char *zErrMsg = 0;
1.4 misho 16391: if( nArg<2 ){
16392: raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
16393: rc = 1;
16394: goto meta_command_exit;
16395: }
1.2 misho 16396: zFile = azArg[1];
16397: zProc = nArg>=3 ? azArg[2] : 0;
1.4 misho 16398: open_db(p, 0);
1.2 misho 16399: rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
16400: if( rc!=SQLITE_OK ){
1.4 misho 16401: utf8_printf(stderr, "Error: %s\n", zErrMsg);
1.2 misho 16402: sqlite3_free(zErrMsg);
16403: rc = 1;
16404: }
16405: }else
16406: #endif
16407:
1.4 misho 16408: if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
16409: if( nArg!=2 ){
16410: raw_printf(stderr, "Usage: .log FILENAME\n");
16411: rc = 1;
16412: }else{
16413: const char *zFile = azArg[1];
16414: output_file_close(p->pLog);
1.4.2.2 ! misho 16415: p->pLog = output_file_open(zFile, 0);
1.4 misho 16416: }
1.2 misho 16417: }else
16418:
1.4 misho 16419: if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
16420: const char *zMode = nArg>=2 ? azArg[1] : "";
1.4.2.2 ! misho 16421: int n2 = strlen30(zMode);
1.4 misho 16422: int c2 = zMode[0];
16423: if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
1.2 misho 16424: p->mode = MODE_Line;
1.4.2.1 misho 16425: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.4 misho 16426: }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
1.2 misho 16427: p->mode = MODE_Column;
1.4.2.1 misho 16428: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.4 misho 16429: }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
1.2 misho 16430: p->mode = MODE_List;
1.4.2.1 misho 16431: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
16432: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.4 misho 16433: }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
1.2 misho 16434: p->mode = MODE_Html;
1.4 misho 16435: }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
1.2 misho 16436: p->mode = MODE_Tcl;
1.4 misho 16437: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
1.4.2.1 misho 16438: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.4 misho 16439: }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
1.2 misho 16440: p->mode = MODE_Csv;
1.4 misho 16441: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
16442: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
16443: }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
1.2 misho 16444: p->mode = MODE_List;
1.4 misho 16445: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
16446: }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
1.2 misho 16447: p->mode = MODE_Insert;
1.4 misho 16448: set_table_name(p, nArg>=3 ? azArg[2] : "table");
1.4.2.1 misho 16449: }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
16450: p->mode = MODE_Quote;
1.4 misho 16451: }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
16452: p->mode = MODE_Ascii;
16453: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
16454: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
1.4.2.2 ! misho 16455: }else if( nArg==1 ){
! 16456: raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
! 16457: }else{
1.4 misho 16458: raw_printf(stderr, "Error: mode should be one of: "
1.4.2.1 misho 16459: "ascii column csv html insert line list quote tabs tcl\n");
1.2 misho 16460: rc = 1;
16461: }
1.4 misho 16462: p->cMode = p->mode;
1.2 misho 16463: }else
16464:
1.4 misho 16465: if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
16466: if( nArg==2 ){
16467: sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
16468: "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
16469: }else{
16470: raw_printf(stderr, "Usage: .nullvalue STRING\n");
1.2 misho 16471: rc = 1;
16472: }
16473: }else
16474:
1.4 misho 16475: if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
1.4.2.1 misho 16476: char *zNewFilename; /* Name of the database file to open */
16477: int iName = 1; /* Index in azArg[] of the filename */
16478: int newFlag = 0; /* True to delete file before opening */
16479: /* Close the existing database */
16480: session_close_all(p);
1.4.2.2 ! misho 16481: close_db(p->db);
1.4 misho 16482: p->db = 0;
1.4.2.1 misho 16483: p->zDbFilename = 0;
16484: sqlite3_free(p->zFreeOnClose);
16485: p->zFreeOnClose = 0;
1.4.2.2 ! misho 16486: p->openMode = SHELL_OPEN_UNSPEC;
! 16487: p->szMax = 0;
1.4.2.1 misho 16488: /* Check for command-line arguments */
16489: for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
16490: const char *z = azArg[iName];
16491: if( optionMatch(z,"new") ){
16492: newFlag = 1;
1.4.2.2 ! misho 16493: #ifdef SQLITE_HAVE_ZLIB
! 16494: }else if( optionMatch(z, "zip") ){
! 16495: p->openMode = SHELL_OPEN_ZIPFILE;
! 16496: #endif
! 16497: }else if( optionMatch(z, "append") ){
! 16498: p->openMode = SHELL_OPEN_APPENDVFS;
! 16499: }else if( optionMatch(z, "readonly") ){
! 16500: p->openMode = SHELL_OPEN_READONLY;
! 16501: #ifdef SQLITE_ENABLE_DESERIALIZE
! 16502: }else if( optionMatch(z, "deserialize") ){
! 16503: p->openMode = SHELL_OPEN_DESERIALIZE;
! 16504: }else if( optionMatch(z, "hexdb") ){
! 16505: p->openMode = SHELL_OPEN_HEXDB;
! 16506: }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
! 16507: p->szMax = integerValue(azArg[++iName]);
! 16508: #endif /* SQLITE_ENABLE_DESERIALIZE */
1.4.2.1 misho 16509: }else if( z[0]=='-' ){
16510: utf8_printf(stderr, "unknown option: %s\n", z);
16511: rc = 1;
16512: goto meta_command_exit;
16513: }
16514: }
16515: /* If a filename is specified, try to open it first */
16516: zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
1.4.2.2 ! misho 16517: if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
1.4.2.1 misho 16518: if( newFlag ) shellDeleteFile(zNewFilename);
16519: p->zDbFilename = zNewFilename;
1.4.2.2 ! misho 16520: open_db(p, OPEN_DB_KEEPALIVE);
1.4.2.1 misho 16521: if( p->db==0 ){
16522: utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
16523: sqlite3_free(zNewFilename);
16524: }else{
16525: p->zFreeOnClose = zNewFilename;
16526: }
16527: }
16528: if( p->db==0 ){
16529: /* As a fall-back open a TEMP database */
16530: p->zDbFilename = 0;
16531: open_db(p, 0);
1.4 misho 16532: }
1.2 misho 16533: }else
16534:
1.4.2.2 ! misho 16535: if( (c=='o'
! 16536: && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
! 16537: || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
1.4 misho 16538: ){
16539: const char *zFile = nArg>=2 ? azArg[1] : "stdout";
1.4.2.2 ! misho 16540: int bTxtMode = 0;
! 16541: if( azArg[0][0]=='e' ){
! 16542: /* Transform the ".excel" command into ".once -x" */
! 16543: nArg = 2;
! 16544: azArg[0] = "once";
! 16545: zFile = azArg[1] = "-x";
! 16546: n = 4;
! 16547: }
1.4 misho 16548: if( nArg>2 ){
1.4.2.2 ! misho 16549: utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
1.4 misho 16550: rc = 1;
16551: goto meta_command_exit;
16552: }
16553: if( n>1 && strncmp(azArg[0], "once", n)==0 ){
16554: if( nArg<2 ){
1.4.2.2 ! misho 16555: raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
1.4 misho 16556: rc = 1;
16557: goto meta_command_exit;
16558: }
16559: p->outCount = 2;
1.3 misho 16560: }else{
1.4 misho 16561: p->outCount = 0;
1.2 misho 16562: }
1.4 misho 16563: output_reset(p);
1.4.2.2 ! misho 16564: if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
! 16565: #ifndef SQLITE_NOHAVE_SYSTEM
! 16566: if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
! 16567: p->doXdgOpen = 1;
! 16568: outputModePush(p);
! 16569: if( zFile[1]=='x' ){
! 16570: newTempFile(p, "csv");
! 16571: p->mode = MODE_Csv;
! 16572: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
! 16573: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
! 16574: }else{
! 16575: newTempFile(p, "txt");
! 16576: bTxtMode = 1;
! 16577: }
! 16578: zFile = p->zTempFile;
! 16579: }
! 16580: #endif /* SQLITE_NOHAVE_SYSTEM */
1.4 misho 16581: if( zFile[0]=='|' ){
16582: #ifdef SQLITE_OMIT_POPEN
16583: raw_printf(stderr, "Error: pipes are not supported in this OS\n");
16584: rc = 1;
16585: p->out = stdout;
16586: #else
16587: p->out = popen(zFile + 1, "w");
1.3 misho 16588: if( p->out==0 ){
1.4 misho 16589: utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
1.3 misho 16590: p->out = stdout;
16591: rc = 1;
16592: }else{
1.4 misho 16593: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
1.3 misho 16594: }
1.4 misho 16595: #endif
1.2 misho 16596: }else{
1.4.2.2 ! misho 16597: p->out = output_file_open(zFile, bTxtMode);
1.2 misho 16598: if( p->out==0 ){
1.4 misho 16599: if( strcmp(zFile,"off")!=0 ){
16600: utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
1.3 misho 16601: }
1.4.2.2 ! misho 16602: p->out = stdout;
! 16603: rc = 1;
! 16604: } else {
! 16605: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
! 16606: }
! 16607: }
! 16608: }else
! 16609:
! 16610: if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
! 16611: open_db(p,0);
! 16612: if( nArg<=1 ) goto parameter_syntax_error;
! 16613:
! 16614: /* .parameter clear
! 16615: ** Clear all bind parameters by dropping the TEMP table that holds them.
! 16616: */
! 16617: if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
! 16618: int wrSchema = 0;
! 16619: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
! 16620: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
! 16621: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
! 16622: 0, 0, 0);
! 16623: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
! 16624: }else
! 16625:
! 16626: /* .parameter list
! 16627: ** List all bind parameters.
! 16628: */
! 16629: if( nArg==2 && strcmp(azArg[1],"list")==0 ){
! 16630: sqlite3_stmt *pStmt = 0;
! 16631: int rx;
! 16632: int len = 0;
! 16633: rx = sqlite3_prepare_v2(p->db,
! 16634: "SELECT max(length(key)) "
! 16635: "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
! 16636: if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
! 16637: len = sqlite3_column_int(pStmt, 0);
! 16638: if( len>40 ) len = 40;
! 16639: }
! 16640: sqlite3_finalize(pStmt);
! 16641: pStmt = 0;
! 16642: if( len ){
! 16643: rx = sqlite3_prepare_v2(p->db,
! 16644: "SELECT key, quote(value) "
! 16645: "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
! 16646: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 16647: utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
! 16648: sqlite3_column_text(pStmt,1));
! 16649: }
! 16650: sqlite3_finalize(pStmt);
! 16651: }
! 16652: }else
! 16653:
! 16654: /* .parameter init
! 16655: ** Make sure the TEMP table used to hold bind parameters exists.
! 16656: ** Create it if necessary.
! 16657: */
! 16658: if( nArg==2 && strcmp(azArg[1],"init")==0 ){
! 16659: bind_table_init(p);
! 16660: }else
! 16661:
! 16662: /* .parameter set NAME VALUE
! 16663: ** Set or reset a bind parameter. NAME should be the full parameter
! 16664: ** name exactly as it appears in the query. (ex: $abc, @def). The
! 16665: ** VALUE can be in either SQL literal notation, or if not it will be
! 16666: ** understood to be a text string.
! 16667: */
! 16668: if( nArg==4 && strcmp(azArg[1],"set")==0 ){
! 16669: int rx;
! 16670: char *zSql;
! 16671: sqlite3_stmt *pStmt;
! 16672: const char *zKey = azArg[2];
! 16673: const char *zValue = azArg[3];
! 16674: bind_table_init(p);
! 16675: zSql = sqlite3_mprintf(
! 16676: "REPLACE INTO temp.sqlite_parameters(key,value)"
! 16677: "VALUES(%Q,%s);", zKey, zValue);
! 16678: if( zSql==0 ) shell_out_of_memory();
! 16679: pStmt = 0;
! 16680: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
! 16681: sqlite3_free(zSql);
! 16682: if( rx!=SQLITE_OK ){
! 16683: sqlite3_finalize(pStmt);
! 16684: pStmt = 0;
! 16685: zSql = sqlite3_mprintf(
! 16686: "REPLACE INTO temp.sqlite_parameters(key,value)"
! 16687: "VALUES(%Q,%Q);", zKey, zValue);
! 16688: if( zSql==0 ) shell_out_of_memory();
! 16689: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
! 16690: sqlite3_free(zSql);
! 16691: if( rx!=SQLITE_OK ){
! 16692: utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
! 16693: sqlite3_finalize(pStmt);
! 16694: pStmt = 0;
! 16695: rc = 1;
! 16696: }
1.2 misho 16697: }
1.4.2.2 ! misho 16698: sqlite3_step(pStmt);
! 16699: sqlite3_finalize(pStmt);
! 16700: }else
! 16701:
! 16702: /* .parameter unset NAME
! 16703: ** Remove the NAME binding from the parameter binding table, if it
! 16704: ** exists.
! 16705: */
! 16706: if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
! 16707: char *zSql = sqlite3_mprintf(
! 16708: "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
! 16709: if( zSql==0 ) shell_out_of_memory();
! 16710: sqlite3_exec(p->db, zSql, 0, 0, 0);
! 16711: sqlite3_free(zSql);
! 16712: }else
! 16713: /* If no command name matches, show a syntax error */
! 16714: parameter_syntax_error:
! 16715: showHelp(p->out, "parameter");
1.2 misho 16716: }else
16717:
1.3 misho 16718: if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
16719: int i;
16720: for(i=1; i<nArg; i++){
1.4 misho 16721: if( i>1 ) raw_printf(p->out, " ");
16722: utf8_printf(p->out, "%s", azArg[i]);
1.3 misho 16723: }
1.4 misho 16724: raw_printf(p->out, "\n");
1.3 misho 16725: }else
16726:
1.4.2.2 ! misho 16727: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
! 16728: if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
! 16729: int i;
! 16730: int nn = 0;
! 16731: p->flgProgress = 0;
! 16732: p->mxProgress = 0;
! 16733: p->nProgress = 0;
! 16734: for(i=1; i<nArg; i++){
! 16735: const char *z = azArg[i];
! 16736: if( z[0]=='-' ){
! 16737: z++;
! 16738: if( z[0]=='-' ) z++;
! 16739: if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
! 16740: p->flgProgress |= SHELL_PROGRESS_QUIET;
! 16741: continue;
! 16742: }
! 16743: if( strcmp(z,"reset")==0 ){
! 16744: p->flgProgress |= SHELL_PROGRESS_RESET;
! 16745: continue;
! 16746: }
! 16747: if( strcmp(z,"once")==0 ){
! 16748: p->flgProgress |= SHELL_PROGRESS_ONCE;
! 16749: continue;
! 16750: }
! 16751: if( strcmp(z,"limit")==0 ){
! 16752: if( i+1>=nArg ){
! 16753: utf8_printf(stderr, "Error: missing argument on --limit\n");
! 16754: rc = 1;
! 16755: goto meta_command_exit;
! 16756: }else{
! 16757: p->mxProgress = (int)integerValue(azArg[++i]);
! 16758: }
! 16759: continue;
! 16760: }
! 16761: utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
! 16762: rc = 1;
! 16763: goto meta_command_exit;
! 16764: }else{
! 16765: nn = (int)integerValue(z);
! 16766: }
! 16767: }
! 16768: open_db(p, 0);
! 16769: sqlite3_progress_handler(p->db, nn, progress_handler, p);
! 16770: }else
! 16771: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
! 16772:
1.4 misho 16773: if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
1.2 misho 16774: if( nArg >= 2) {
16775: strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
16776: }
16777: if( nArg >= 3) {
16778: strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
16779: }
16780: }else
16781:
1.4 misho 16782: if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
1.2 misho 16783: rc = 2;
16784: }else
16785:
1.4 misho 16786: if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
1.4.2.2 ! misho 16787: FILE *inSaved = p->in;
! 16788: int savedLineno = p->lineno;
1.4 misho 16789: if( nArg!=2 ){
16790: raw_printf(stderr, "Usage: .read FILE\n");
16791: rc = 1;
16792: goto meta_command_exit;
16793: }
1.4.2.2 ! misho 16794: p->in = fopen(azArg[1], "rb");
! 16795: if( p->in==0 ){
1.4 misho 16796: utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
1.2 misho 16797: rc = 1;
16798: }else{
1.4.2.2 ! misho 16799: rc = process_input(p);
! 16800: fclose(p->in);
1.2 misho 16801: }
1.4.2.2 ! misho 16802: p->in = inSaved;
! 16803: p->lineno = savedLineno;
1.2 misho 16804: }else
16805:
1.4 misho 16806: if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
1.2 misho 16807: const char *zSrcFile;
16808: const char *zDb;
16809: sqlite3 *pSrc;
16810: sqlite3_backup *pBackup;
16811: int nTimeout = 0;
16812:
16813: if( nArg==2 ){
16814: zSrcFile = azArg[1];
16815: zDb = "main";
1.4 misho 16816: }else if( nArg==3 ){
1.2 misho 16817: zSrcFile = azArg[2];
16818: zDb = azArg[1];
1.4 misho 16819: }else{
16820: raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
16821: rc = 1;
16822: goto meta_command_exit;
1.2 misho 16823: }
16824: rc = sqlite3_open(zSrcFile, &pSrc);
16825: if( rc!=SQLITE_OK ){
1.4 misho 16826: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
1.4.2.2 ! misho 16827: close_db(pSrc);
1.2 misho 16828: return 1;
16829: }
1.4 misho 16830: open_db(p, 0);
1.2 misho 16831: pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
16832: if( pBackup==0 ){
1.4 misho 16833: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.4.2.2 ! misho 16834: close_db(pSrc);
1.2 misho 16835: return 1;
16836: }
16837: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
16838: || rc==SQLITE_BUSY ){
16839: if( rc==SQLITE_BUSY ){
16840: if( nTimeout++ >= 3 ) break;
16841: sqlite3_sleep(100);
16842: }
16843: }
16844: sqlite3_backup_finish(pBackup);
16845: if( rc==SQLITE_DONE ){
16846: rc = 0;
16847: }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
1.4 misho 16848: raw_printf(stderr, "Error: source database is busy\n");
1.2 misho 16849: rc = 1;
16850: }else{
1.4 misho 16851: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 16852: rc = 1;
16853: }
1.4.2.2 ! misho 16854: close_db(pSrc);
1.2 misho 16855: }else
16856:
1.4 misho 16857: if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
16858: if( nArg==2 ){
1.4.2.2 ! misho 16859: p->scanstatsOn = (u8)booleanValue(azArg[1]);
1.4 misho 16860: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
16861: raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
16862: #endif
16863: }else{
16864: raw_printf(stderr, "Usage: .scanstats on|off\n");
16865: rc = 1;
16866: }
16867: }else
16868:
16869: if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
1.4.2.2 ! misho 16870: ShellText sSelect;
1.4 misho 16871: ShellState data;
1.2 misho 16872: char *zErrMsg = 0;
1.4.2.2 ! misho 16873: const char *zDiv = "(";
! 16874: const char *zName = 0;
! 16875: int iSchema = 0;
! 16876: int bDebug = 0;
! 16877: int ii;
! 16878:
1.4 misho 16879: open_db(p, 0);
1.2 misho 16880: memcpy(&data, p, sizeof(data));
16881: data.showHeader = 0;
1.4 misho 16882: data.cMode = data.mode = MODE_Semi;
1.4.2.2 ! misho 16883: initText(&sSelect);
! 16884: for(ii=1; ii<nArg; ii++){
! 16885: if( optionMatch(azArg[ii],"indent") ){
! 16886: data.cMode = data.mode = MODE_Pretty;
! 16887: }else if( optionMatch(azArg[ii],"debug") ){
! 16888: bDebug = 1;
! 16889: }else if( zName==0 ){
! 16890: zName = azArg[ii];
! 16891: }else{
! 16892: raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
! 16893: rc = 1;
! 16894: goto meta_command_exit;
! 16895: }
1.4 misho 16896: }
1.4.2.2 ! misho 16897: if( zName!=0 ){
! 16898: int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0;
! 16899: if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){
1.2 misho 16900: char *new_argv[2], *new_colv[2];
1.4.2.2 ! misho 16901: new_argv[0] = sqlite3_mprintf(
! 16902: "CREATE TABLE %s (\n"
1.2 misho 16903: " type text,\n"
16904: " name text,\n"
16905: " tbl_name text,\n"
16906: " rootpage integer,\n"
16907: " sql text\n"
1.4.2.2 ! misho 16908: ")", isMaster ? "sqlite_master" : "sqlite_temp_master");
1.2 misho 16909: new_argv[1] = 0;
16910: new_colv[0] = "sql";
16911: new_colv[1] = 0;
16912: callback(&data, 1, new_argv, new_colv);
1.4.2.2 ! misho 16913: sqlite3_free(new_argv[0]);
! 16914: }
! 16915: }
! 16916: if( zDiv ){
! 16917: sqlite3_stmt *pStmt = 0;
! 16918: rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
! 16919: -1, &pStmt, 0);
! 16920: if( rc ){
! 16921: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
! 16922: sqlite3_finalize(pStmt);
! 16923: rc = 1;
! 16924: goto meta_command_exit;
! 16925: }
! 16926: appendText(&sSelect, "SELECT sql FROM", 0);
! 16927: iSchema = 0;
! 16928: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 16929: const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
! 16930: char zScNum[30];
! 16931: sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
! 16932: appendText(&sSelect, zDiv, 0);
! 16933: zDiv = " UNION ALL ";
! 16934: appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
! 16935: if( sqlite3_stricmp(zDb, "main")!=0 ){
! 16936: appendText(&sSelect, zDb, '"');
! 16937: }else{
! 16938: appendText(&sSelect, "NULL", 0);
! 16939: }
! 16940: appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
! 16941: appendText(&sSelect, zScNum, 0);
! 16942: appendText(&sSelect, " AS snum, ", 0);
! 16943: appendText(&sSelect, zDb, '\'');
! 16944: appendText(&sSelect, " AS sname FROM ", 0);
! 16945: appendText(&sSelect, zDb, '"');
! 16946: appendText(&sSelect, ".sqlite_master", 0);
! 16947: }
! 16948: sqlite3_finalize(pStmt);
! 16949: #ifdef SQLITE_INTROSPECTION_PRAGMAS
! 16950: if( zName ){
! 16951: appendText(&sSelect,
! 16952: " UNION ALL SELECT shell_module_schema(name),"
! 16953: " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
! 16954: }
! 16955: #endif
! 16956: appendText(&sSelect, ") WHERE ", 0);
! 16957: if( zName ){
! 16958: char *zQarg = sqlite3_mprintf("%Q", zName);
! 16959: int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
! 16960: strchr(zName, '[') != 0;
! 16961: if( strchr(zName, '.') ){
! 16962: appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
! 16963: }else{
! 16964: appendText(&sSelect, "lower(tbl_name)", 0);
! 16965: }
! 16966: appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
! 16967: appendText(&sSelect, zQarg, 0);
! 16968: if( !bGlob ){
! 16969: appendText(&sSelect, " ESCAPE '\\' ", 0);
! 16970: }
! 16971: appendText(&sSelect, " AND ", 0);
! 16972: sqlite3_free(zQarg);
! 16973: }
! 16974: appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
! 16975: " ORDER BY snum, rowid", 0);
! 16976: if( bDebug ){
! 16977: utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
1.2 misho 16978: }else{
1.4.2.2 ! misho 16979: rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
1.2 misho 16980: }
1.4.2.2 ! misho 16981: freeText(&sSelect);
1.2 misho 16982: }
16983: if( zErrMsg ){
1.4 misho 16984: utf8_printf(stderr,"Error: %s\n", zErrMsg);
1.2 misho 16985: sqlite3_free(zErrMsg);
16986: rc = 1;
16987: }else if( rc != SQLITE_OK ){
1.4 misho 16988: raw_printf(stderr,"Error: querying schema information\n");
1.2 misho 16989: rc = 1;
16990: }else{
16991: rc = 0;
16992: }
16993: }else
16994:
1.4 misho 16995: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
16996: if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
1.4.2.1 misho 16997: sqlite3SelectTrace = (int)integerValue(azArg[1]);
1.4 misho 16998: }else
16999: #endif
17000:
17001: #if defined(SQLITE_ENABLE_SESSION)
17002: if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
17003: OpenSession *pSession = &p->aSession[0];
17004: char **azCmd = &azArg[1];
17005: int iSes = 0;
17006: int nCmd = nArg - 1;
17007: int i;
17008: if( nArg<=1 ) goto session_syntax_error;
17009: open_db(p, 0);
17010: if( nArg>=3 ){
17011: for(iSes=0; iSes<p->nSession; iSes++){
17012: if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
17013: }
17014: if( iSes<p->nSession ){
17015: pSession = &p->aSession[iSes];
17016: azCmd++;
17017: nCmd--;
17018: }else{
17019: pSession = &p->aSession[0];
17020: iSes = 0;
17021: }
17022: }
17023:
17024: /* .session attach TABLE
17025: ** Invoke the sqlite3session_attach() interface to attach a particular
17026: ** table so that it is never filtered.
17027: */
17028: if( strcmp(azCmd[0],"attach")==0 ){
17029: if( nCmd!=2 ) goto session_syntax_error;
17030: if( pSession->p==0 ){
17031: session_not_open:
17032: raw_printf(stderr, "ERROR: No sessions are open\n");
17033: }else{
17034: rc = sqlite3session_attach(pSession->p, azCmd[1]);
17035: if( rc ){
17036: raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
17037: rc = 0;
17038: }
17039: }
17040: }else
17041:
17042: /* .session changeset FILE
17043: ** .session patchset FILE
17044: ** Write a changeset or patchset into a file. The file is overwritten.
17045: */
17046: if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
17047: FILE *out = 0;
17048: if( nCmd!=2 ) goto session_syntax_error;
17049: if( pSession->p==0 ) goto session_not_open;
17050: out = fopen(azCmd[1], "wb");
17051: if( out==0 ){
17052: utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
17053: }else{
17054: int szChng;
17055: void *pChng;
17056: if( azCmd[0][0]=='c' ){
17057: rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
17058: }else{
17059: rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
17060: }
17061: if( rc ){
17062: printf("Error: error code %d\n", rc);
17063: rc = 0;
17064: }
17065: if( pChng
17066: && fwrite(pChng, szChng, 1, out)!=1 ){
17067: raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
17068: szChng);
17069: }
17070: sqlite3_free(pChng);
17071: fclose(out);
17072: }
17073: }else
17074:
17075: /* .session close
17076: ** Close the identified session
17077: */
17078: if( strcmp(azCmd[0], "close")==0 ){
17079: if( nCmd!=1 ) goto session_syntax_error;
17080: if( p->nSession ){
17081: session_close(pSession);
17082: p->aSession[iSes] = p->aSession[--p->nSession];
17083: }
17084: }else
17085:
17086: /* .session enable ?BOOLEAN?
17087: ** Query or set the enable flag
17088: */
17089: if( strcmp(azCmd[0], "enable")==0 ){
17090: int ii;
17091: if( nCmd>2 ) goto session_syntax_error;
17092: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
17093: if( p->nSession ){
17094: ii = sqlite3session_enable(pSession->p, ii);
17095: utf8_printf(p->out, "session %s enable flag = %d\n",
17096: pSession->zName, ii);
17097: }
17098: }else
17099:
17100: /* .session filter GLOB ....
17101: ** Set a list of GLOB patterns of table names to be excluded.
17102: */
17103: if( strcmp(azCmd[0], "filter")==0 ){
17104: int ii, nByte;
17105: if( nCmd<2 ) goto session_syntax_error;
17106: if( p->nSession ){
17107: for(ii=0; ii<pSession->nFilter; ii++){
17108: sqlite3_free(pSession->azFilter[ii]);
17109: }
17110: sqlite3_free(pSession->azFilter);
17111: nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
17112: pSession->azFilter = sqlite3_malloc( nByte );
17113: if( pSession->azFilter==0 ){
17114: raw_printf(stderr, "Error: out or memory\n");
17115: exit(1);
17116: }
17117: for(ii=1; ii<nCmd; ii++){
17118: pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
17119: }
17120: pSession->nFilter = ii-1;
17121: }
17122: }else
17123:
17124: /* .session indirect ?BOOLEAN?
17125: ** Query or set the indirect flag
17126: */
17127: if( strcmp(azCmd[0], "indirect")==0 ){
17128: int ii;
17129: if( nCmd>2 ) goto session_syntax_error;
17130: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
17131: if( p->nSession ){
17132: ii = sqlite3session_indirect(pSession->p, ii);
17133: utf8_printf(p->out, "session %s indirect flag = %d\n",
17134: pSession->zName, ii);
17135: }
17136: }else
17137:
17138: /* .session isempty
17139: ** Determine if the session is empty
17140: */
17141: if( strcmp(azCmd[0], "isempty")==0 ){
17142: int ii;
17143: if( nCmd!=1 ) goto session_syntax_error;
17144: if( p->nSession ){
17145: ii = sqlite3session_isempty(pSession->p);
17146: utf8_printf(p->out, "session %s isempty flag = %d\n",
17147: pSession->zName, ii);
17148: }
17149: }else
17150:
17151: /* .session list
17152: ** List all currently open sessions
17153: */
17154: if( strcmp(azCmd[0],"list")==0 ){
17155: for(i=0; i<p->nSession; i++){
17156: utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
17157: }
17158: }else
17159:
17160: /* .session open DB NAME
17161: ** Open a new session called NAME on the attached database DB.
17162: ** DB is normally "main".
17163: */
17164: if( strcmp(azCmd[0],"open")==0 ){
17165: char *zName;
17166: if( nCmd!=3 ) goto session_syntax_error;
17167: zName = azCmd[2];
17168: if( zName[0]==0 ) goto session_syntax_error;
17169: for(i=0; i<p->nSession; i++){
17170: if( strcmp(p->aSession[i].zName,zName)==0 ){
17171: utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
17172: goto meta_command_exit;
17173: }
17174: }
17175: if( p->nSession>=ArraySize(p->aSession) ){
17176: raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
17177: goto meta_command_exit;
17178: }
17179: pSession = &p->aSession[p->nSession];
17180: rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
17181: if( rc ){
17182: raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
17183: rc = 0;
17184: goto meta_command_exit;
17185: }
17186: pSession->nFilter = 0;
17187: sqlite3session_table_filter(pSession->p, session_filter, pSession);
17188: p->nSession++;
17189: pSession->zName = sqlite3_mprintf("%s", zName);
17190: }else
17191: /* If no command name matches, show a syntax error */
17192: session_syntax_error:
1.4.2.2 ! misho 17193: showHelp(p->out, "session");
1.4 misho 17194: }else
17195: #endif
17196:
17197: #ifdef SQLITE_DEBUG
17198: /* Undocumented commands for internal testing. Subject to change
17199: ** without notice. */
17200: if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
17201: if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
17202: int i, v;
17203: for(i=1; i<nArg; i++){
17204: v = booleanValue(azArg[i]);
17205: utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
17206: }
17207: }
17208: if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
17209: int i; sqlite3_int64 v;
17210: for(i=1; i<nArg; i++){
17211: char zBuf[200];
17212: v = integerValue(azArg[i]);
17213: sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
17214: utf8_printf(p->out, "%s", zBuf);
17215: }
17216: }
17217: }else
17218: #endif
17219:
1.4.2.1 misho 17220: if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
17221: int bIsInit = 0; /* True to initialize the SELFTEST table */
17222: int bVerbose = 0; /* Verbose output */
17223: int bSelftestExists; /* True if SELFTEST already exists */
1.4.2.2 ! misho 17224: int i, k; /* Loop counters */
1.4.2.1 misho 17225: int nTest = 0; /* Number of tests runs */
17226: int nErr = 0; /* Number of errors seen */
17227: ShellText str; /* Answer for a query */
1.4.2.2 ! misho 17228: sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
1.4.2.1 misho 17229:
17230: open_db(p,0);
17231: for(i=1; i<nArg; i++){
17232: const char *z = azArg[i];
17233: if( z[0]=='-' && z[1]=='-' ) z++;
17234: if( strcmp(z,"-init")==0 ){
17235: bIsInit = 1;
17236: }else
17237: if( strcmp(z,"-v")==0 ){
17238: bVerbose++;
17239: }else
17240: {
17241: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
17242: azArg[i], azArg[0]);
17243: raw_printf(stderr, "Should be one of: --init -v\n");
17244: rc = 1;
17245: goto meta_command_exit;
17246: }
17247: }
17248: if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
17249: != SQLITE_OK ){
17250: bSelftestExists = 0;
17251: }else{
17252: bSelftestExists = 1;
17253: }
17254: if( bIsInit ){
17255: createSelftestTable(p);
17256: bSelftestExists = 1;
17257: }
1.4.2.2 ! misho 17258: initText(&str);
! 17259: appendText(&str, "x", 0);
! 17260: for(k=bSelftestExists; k>=0; k--){
! 17261: if( k==1 ){
! 17262: rc = sqlite3_prepare_v2(p->db,
! 17263: "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
! 17264: -1, &pStmt, 0);
! 17265: }else{
! 17266: rc = sqlite3_prepare_v2(p->db,
! 17267: "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
! 17268: " (1,'run','PRAGMA integrity_check','ok')",
! 17269: -1, &pStmt, 0);
! 17270: }
1.4.2.1 misho 17271: if( rc ){
17272: raw_printf(stderr, "Error querying the selftest table\n");
17273: rc = 1;
1.4.2.2 ! misho 17274: sqlite3_finalize(pStmt);
1.4.2.1 misho 17275: goto meta_command_exit;
17276: }
1.4.2.2 ! misho 17277: for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
! 17278: int tno = sqlite3_column_int(pStmt, 0);
! 17279: const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
! 17280: const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
! 17281: const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
! 17282:
! 17283: k = 0;
! 17284: if( bVerbose>0 ){
! 17285: char *zQuote = sqlite3_mprintf("%q", zSql);
! 17286: printf("%d: %s %s\n", tno, zOp, zSql);
! 17287: sqlite3_free(zQuote);
1.4.2.1 misho 17288: }
1.4.2.2 ! misho 17289: if( strcmp(zOp,"memo")==0 ){
! 17290: utf8_printf(p->out, "%s\n", zSql);
! 17291: }else
! 17292: if( strcmp(zOp,"run")==0 ){
! 17293: char *zErrMsg = 0;
! 17294: str.n = 0;
! 17295: str.z[0] = 0;
! 17296: rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
! 17297: nTest++;
! 17298: if( bVerbose ){
! 17299: utf8_printf(p->out, "Result: %s\n", str.z);
! 17300: }
! 17301: if( rc || zErrMsg ){
! 17302: nErr++;
! 17303: rc = 1;
! 17304: utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
! 17305: sqlite3_free(zErrMsg);
! 17306: }else if( strcmp(zAns,str.z)!=0 ){
! 17307: nErr++;
! 17308: rc = 1;
! 17309: utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
! 17310: utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
! 17311: }
! 17312: }else
! 17313: {
! 17314: utf8_printf(stderr,
! 17315: "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
1.4.2.1 misho 17316: rc = 1;
1.4.2.2 ! misho 17317: break;
1.4.2.1 misho 17318: }
1.4.2.2 ! misho 17319: } /* End loop over rows of content from SELFTEST */
! 17320: sqlite3_finalize(pStmt);
! 17321: } /* End loop over k */
1.4.2.1 misho 17322: freeText(&str);
17323: utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
17324: }else
17325:
1.4 misho 17326: if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
17327: if( nArg<2 || nArg>3 ){
17328: raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
17329: rc = 1;
17330: }
17331: if( nArg>=2 ){
17332: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
17333: "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
17334: }
17335: if( nArg>=3 ){
17336: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
17337: "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
17338: }
17339: }else
17340:
1.4.2.1 misho 17341: if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
17342: const char *zLike = 0; /* Which table to checksum. 0 means everything */
17343: int i; /* Loop counter */
17344: int bSchema = 0; /* Also hash the schema */
17345: int bSeparate = 0; /* Hash each table separately */
17346: int iSize = 224; /* Hash algorithm to use */
17347: int bDebug = 0; /* Only show the query that would have run */
17348: sqlite3_stmt *pStmt; /* For querying tables names */
17349: char *zSql; /* SQL to be run */
17350: char *zSep; /* Separator */
17351: ShellText sSql; /* Complete SQL for the query to run the hash */
17352: ShellText sQuery; /* Set of queries used to read all content */
17353: open_db(p, 0);
17354: for(i=1; i<nArg; i++){
17355: const char *z = azArg[i];
17356: if( z[0]=='-' ){
17357: z++;
17358: if( z[0]=='-' ) z++;
17359: if( strcmp(z,"schema")==0 ){
17360: bSchema = 1;
17361: }else
1.4.2.2 ! misho 17362: if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
! 17363: || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
1.4.2.1 misho 17364: ){
17365: iSize = atoi(&z[5]);
17366: }else
17367: if( strcmp(z,"debug")==0 ){
17368: bDebug = 1;
17369: }else
17370: {
17371: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
17372: azArg[i], azArg[0]);
17373: raw_printf(stderr, "Should be one of: --schema"
1.4.2.2 ! misho 17374: " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
1.4.2.1 misho 17375: rc = 1;
17376: goto meta_command_exit;
17377: }
17378: }else if( zLike ){
17379: raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
17380: rc = 1;
17381: goto meta_command_exit;
17382: }else{
17383: zLike = z;
17384: bSeparate = 1;
1.4.2.2 ! misho 17385: if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
1.4.2.1 misho 17386: }
17387: }
17388: if( bSchema ){
17389: zSql = "SELECT lower(name) FROM sqlite_master"
17390: " WHERE type='table' AND coalesce(rootpage,0)>1"
17391: " UNION ALL SELECT 'sqlite_master'"
17392: " ORDER BY 1 collate nocase";
17393: }else{
17394: zSql = "SELECT lower(name) FROM sqlite_master"
17395: " WHERE type='table' AND coalesce(rootpage,0)>1"
17396: " AND name NOT LIKE 'sqlite_%'"
17397: " ORDER BY 1 collate nocase";
17398: }
17399: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
17400: initText(&sQuery);
17401: initText(&sSql);
17402: appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
17403: zSep = "VALUES(";
17404: while( SQLITE_ROW==sqlite3_step(pStmt) ){
17405: const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
17406: if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
17407: if( strncmp(zTab, "sqlite_",7)!=0 ){
17408: appendText(&sQuery,"SELECT * FROM ", 0);
17409: appendText(&sQuery,zTab,'"');
17410: appendText(&sQuery," NOT INDEXED;", 0);
17411: }else if( strcmp(zTab, "sqlite_master")==0 ){
17412: appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
17413: " ORDER BY name;", 0);
17414: }else if( strcmp(zTab, "sqlite_sequence")==0 ){
17415: appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
17416: " ORDER BY name;", 0);
17417: }else if( strcmp(zTab, "sqlite_stat1")==0 ){
17418: appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
17419: " ORDER BY tbl,idx;", 0);
17420: }else if( strcmp(zTab, "sqlite_stat3")==0
17421: || strcmp(zTab, "sqlite_stat4")==0 ){
17422: appendText(&sQuery, "SELECT * FROM ", 0);
17423: appendText(&sQuery, zTab, 0);
17424: appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
17425: }
17426: appendText(&sSql, zSep, 0);
17427: appendText(&sSql, sQuery.z, '\'');
17428: sQuery.n = 0;
17429: appendText(&sSql, ",", 0);
17430: appendText(&sSql, zTab, '\'');
17431: zSep = "),(";
17432: }
17433: sqlite3_finalize(pStmt);
17434: if( bSeparate ){
17435: zSql = sqlite3_mprintf(
17436: "%s))"
17437: " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
17438: " FROM [sha3sum$query]",
17439: sSql.z, iSize);
17440: }else{
17441: zSql = sqlite3_mprintf(
17442: "%s))"
17443: " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
17444: " FROM [sha3sum$query]",
17445: sSql.z, iSize);
17446: }
17447: freeText(&sQuery);
17448: freeText(&sSql);
17449: if( bDebug ){
17450: utf8_printf(p->out, "%s\n", zSql);
17451: }else{
1.4.2.2 ! misho 17452: shell_exec(p, zSql, 0);
1.4.2.1 misho 17453: }
17454: sqlite3_free(zSql);
17455: }else
17456:
1.4.2.2 ! misho 17457: #ifndef SQLITE_NOHAVE_SYSTEM
1.4 misho 17458: if( c=='s'
17459: && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
17460: ){
17461: char *zCmd;
17462: int i, x;
17463: if( nArg<2 ){
17464: raw_printf(stderr, "Usage: .system COMMAND\n");
17465: rc = 1;
17466: goto meta_command_exit;
17467: }
17468: zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
17469: for(i=2; i<nArg; i++){
17470: zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
17471: zCmd, azArg[i]);
17472: }
17473: x = system(zCmd);
17474: sqlite3_free(zCmd);
17475: if( x ) raw_printf(stderr, "System command returns %d\n", x);
1.2 misho 17476: }else
1.4.2.2 ! misho 17477: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
1.2 misho 17478:
1.4 misho 17479: if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
1.4.2.2 ! misho 17480: static const char *azBool[] = { "off", "on", "trigger", "full"};
1.2 misho 17481: int i;
1.4 misho 17482: if( nArg!=1 ){
17483: raw_printf(stderr, "Usage: .show\n");
17484: rc = 1;
17485: goto meta_command_exit;
17486: }
1.4.2.1 misho 17487: utf8_printf(p->out, "%12.12s: %s\n","echo",
17488: azBool[ShellHasFlag(p, SHFLG_Echo)]);
1.4 misho 17489: utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
17490: utf8_printf(p->out, "%12.12s: %s\n","explain",
17491: p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
17492: utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
17493: utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
17494: utf8_printf(p->out, "%12.12s: ", "nullvalue");
17495: output_c_string(p->out, p->nullValue);
17496: raw_printf(p->out, "\n");
17497: utf8_printf(p->out,"%12.12s: %s\n","output",
1.2 misho 17498: strlen30(p->outfile) ? p->outfile : "stdout");
1.4 misho 17499: utf8_printf(p->out,"%12.12s: ", "colseparator");
17500: output_c_string(p->out, p->colSeparator);
17501: raw_printf(p->out, "\n");
17502: utf8_printf(p->out,"%12.12s: ", "rowseparator");
17503: output_c_string(p->out, p->rowSeparator);
17504: raw_printf(p->out, "\n");
17505: utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
17506: utf8_printf(p->out, "%12.12s: ", "width");
1.2 misho 17507: for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
1.4 misho 17508: raw_printf(p->out, "%d ", p->colWidth[i]);
1.2 misho 17509: }
1.4 misho 17510: raw_printf(p->out, "\n");
1.4.2.1 misho 17511: utf8_printf(p->out, "%12.12s: %s\n", "filename",
17512: p->zDbFilename ? p->zDbFilename : "");
1.2 misho 17513: }else
17514:
1.4 misho 17515: if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
17516: if( nArg==2 ){
1.4.2.2 ! misho 17517: p->statsOn = (u8)booleanValue(azArg[1]);
1.4 misho 17518: }else if( nArg==1 ){
17519: display_stats(p->db, p, 0);
17520: }else{
17521: raw_printf(stderr, "Usage: .stats ?on|off?\n");
17522: rc = 1;
17523: }
1.2 misho 17524: }else
17525:
1.4.2.1 misho 17526: if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
17527: || (c=='i' && (strncmp(azArg[0], "indices", n)==0
17528: || strncmp(azArg[0], "indexes", n)==0) )
17529: ){
1.3 misho 17530: sqlite3_stmt *pStmt;
1.2 misho 17531: char **azResult;
1.3 misho 17532: int nRow, nAlloc;
17533: int ii;
1.4.2.2 ! misho 17534: ShellText s;
! 17535: initText(&s);
1.4 misho 17536: open_db(p, 0);
1.3 misho 17537: rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
1.4.2.2 ! misho 17538: if( rc ){
! 17539: sqlite3_finalize(pStmt);
! 17540: return shellDatabaseError(p->db);
! 17541: }
1.4 misho 17542:
1.4.2.2 ! misho 17543: if( nArg>2 && c=='i' ){
1.4.2.1 misho 17544: /* It is an historical accident that the .indexes command shows an error
17545: ** when called with the wrong number of arguments whereas the .tables
17546: ** command does not. */
17547: raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
17548: rc = 1;
1.4.2.2 ! misho 17549: sqlite3_finalize(pStmt);
1.4.2.1 misho 17550: goto meta_command_exit;
17551: }
1.4.2.2 ! misho 17552: for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
1.3 misho 17553: const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
1.4.2.2 ! misho 17554: if( zDbName==0 ) continue;
! 17555: if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
! 17556: if( sqlite3_stricmp(zDbName, "main")==0 ){
! 17557: appendText(&s, "SELECT name FROM ", 0);
! 17558: }else{
! 17559: appendText(&s, "SELECT ", 0);
! 17560: appendText(&s, zDbName, '\'');
! 17561: appendText(&s, "||'.'||name FROM ", 0);
! 17562: }
! 17563: appendText(&s, zDbName, '"');
! 17564: appendText(&s, ".sqlite_master ", 0);
1.4.2.1 misho 17565: if( c=='t' ){
1.4.2.2 ! misho 17566: appendText(&s," WHERE type IN ('table','view')"
! 17567: " AND name NOT LIKE 'sqlite_%'"
! 17568: " AND name LIKE ?1", 0);
1.3 misho 17569: }else{
1.4.2.2 ! misho 17570: appendText(&s," WHERE type='index'"
! 17571: " AND tbl_name LIKE ?1", 0);
1.3 misho 17572: }
17573: }
1.4 misho 17574: rc = sqlite3_finalize(pStmt);
1.4.2.2 ! misho 17575: appendText(&s, " ORDER BY 1", 0);
! 17576: rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
! 17577: freeText(&s);
1.4 misho 17578: if( rc ) return shellDatabaseError(p->db);
17579:
17580: /* Run the SQL statement prepared by the above block. Store the results
17581: ** as an array of nul-terminated strings in azResult[]. */
1.3 misho 17582: nRow = nAlloc = 0;
17583: azResult = 0;
17584: if( nArg>1 ){
17585: sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
1.2 misho 17586: }else{
1.3 misho 17587: sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
17588: }
17589: while( sqlite3_step(pStmt)==SQLITE_ROW ){
17590: if( nRow>=nAlloc ){
17591: char **azNew;
1.4 misho 17592: int n2 = nAlloc*2 + 10;
17593: azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
1.4.2.2 ! misho 17594: if( azNew==0 ) shell_out_of_memory();
1.4 misho 17595: nAlloc = n2;
1.3 misho 17596: azResult = azNew;
17597: }
17598: azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
1.4.2.2 ! misho 17599: if( 0==azResult[nRow] ) shell_out_of_memory();
1.4 misho 17600: nRow++;
1.2 misho 17601: }
1.4 misho 17602: if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
17603: rc = shellDatabaseError(p->db);
17604: }
17605:
17606: /* Pretty-print the contents of array azResult[] to the output */
17607: if( rc==0 && nRow>0 ){
1.2 misho 17608: int len, maxlen = 0;
17609: int i, j;
17610: int nPrintCol, nPrintRow;
1.3 misho 17611: for(i=0; i<nRow; i++){
1.2 misho 17612: len = strlen30(azResult[i]);
17613: if( len>maxlen ) maxlen = len;
17614: }
17615: nPrintCol = 80/(maxlen+2);
17616: if( nPrintCol<1 ) nPrintCol = 1;
17617: nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
17618: for(i=0; i<nPrintRow; i++){
1.3 misho 17619: for(j=i; j<nRow; j+=nPrintRow){
17620: char *zSp = j<nPrintRow ? "" : " ";
1.4 misho 17621: utf8_printf(p->out, "%s%-*s", zSp, maxlen,
17622: azResult[j] ? azResult[j]:"");
1.2 misho 17623: }
1.4 misho 17624: raw_printf(p->out, "\n");
1.2 misho 17625: }
17626: }
1.4 misho 17627:
1.3 misho 17628: for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
17629: sqlite3_free(azResult);
1.2 misho 17630: }else
17631:
1.4.2.1 misho 17632: /* Begin redirecting output to the file "testcase-out.txt" */
17633: if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
17634: output_reset(p);
1.4.2.2 ! misho 17635: p->out = output_file_open("testcase-out.txt", 0);
1.4.2.1 misho 17636: if( p->out==0 ){
17637: raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
17638: }
17639: if( nArg>=2 ){
17640: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
17641: }else{
17642: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
17643: }
17644: }else
17645:
17646: #ifndef SQLITE_UNTESTABLE
1.4.2.2 ! misho 17647: if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
1.2 misho 17648: static const struct {
17649: const char *zCtrlName; /* Name of a test-control option */
17650: int ctrlCode; /* Integer code for that option */
1.4.2.2 ! misho 17651: const char *zUsage; /* Usage notes */
1.2 misho 17652: } aCtrl[] = {
1.4.2.2 ! misho 17653: { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
! 17654: { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
! 17655: /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
! 17656: /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
! 17657: { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
! 17658: /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
! 17659: { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
! 17660: { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
! 17661: { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
! 17662: { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
! 17663: { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
! 17664: #ifdef YYCOVERAGE
! 17665: { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
! 17666: #endif
! 17667: { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
! 17668: { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" },
! 17669: { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
! 17670: { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
! 17671: { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" },
1.2 misho 17672: };
17673: int testctrl = -1;
1.4.2.2 ! misho 17674: int iCtrl = -1;
! 17675: int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
! 17676: int isOk = 0;
1.4 misho 17677: int i, n2;
1.4.2.2 ! misho 17678: const char *zCmd = 0;
! 17679:
1.4 misho 17680: open_db(p, 0);
1.4.2.2 ! misho 17681: zCmd = nArg>=2 ? azArg[1] : "help";
! 17682:
! 17683: /* The argument can optionally begin with "-" or "--" */
! 17684: if( zCmd[0]=='-' && zCmd[1] ){
! 17685: zCmd++;
! 17686: if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
! 17687: }
! 17688:
! 17689: /* --help lists all test-controls */
! 17690: if( strcmp(zCmd,"help")==0 ){
! 17691: utf8_printf(p->out, "Available test-controls:\n");
! 17692: for(i=0; i<ArraySize(aCtrl); i++){
! 17693: utf8_printf(p->out, " .testctrl %s %s\n",
! 17694: aCtrl[i].zCtrlName, aCtrl[i].zUsage);
! 17695: }
! 17696: rc = 1;
! 17697: goto meta_command_exit;
! 17698: }
1.2 misho 17699:
17700: /* convert testctrl text option to value. allow any unique prefix
17701: ** of the option name, or a numerical value. */
1.4.2.2 ! misho 17702: n2 = strlen30(zCmd);
1.4 misho 17703: for(i=0; i<ArraySize(aCtrl); i++){
1.4.2.2 ! misho 17704: if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
1.2 misho 17705: if( testctrl<0 ){
17706: testctrl = aCtrl[i].ctrlCode;
1.4.2.2 ! misho 17707: iCtrl = i;
1.2 misho 17708: }else{
1.4.2.2 ! misho 17709: utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
! 17710: "Use \".testctrl --help\" for help\n", zCmd);
! 17711: rc = 1;
! 17712: goto meta_command_exit;
1.2 misho 17713: }
17714: }
17715: }
1.4.2.2 ! misho 17716: if( testctrl<0 ){
! 17717: utf8_printf(stderr,"Error: unknown test-control: %s\n"
! 17718: "Use \".testctrl --help\" for help\n", zCmd);
1.2 misho 17719: }else{
17720: switch(testctrl){
17721:
17722: /* sqlite3_test_control(int, db, int) */
17723: case SQLITE_TESTCTRL_OPTIMIZATIONS:
1.4 misho 17724: case SQLITE_TESTCTRL_RESERVE:
1.2 misho 17725: if( nArg==3 ){
1.4 misho 17726: int opt = (int)strtol(azArg[2], 0, 0);
17727: rc2 = sqlite3_test_control(testctrl, p->db, opt);
1.4.2.2 ! misho 17728: isOk = 3;
1.2 misho 17729: }
17730: break;
17731:
17732: /* sqlite3_test_control(int) */
1.4 misho 17733: case SQLITE_TESTCTRL_PRNG_SAVE:
17734: case SQLITE_TESTCTRL_PRNG_RESTORE:
1.2 misho 17735: case SQLITE_TESTCTRL_PRNG_RESET:
1.4 misho 17736: case SQLITE_TESTCTRL_BYTEORDER:
1.2 misho 17737: if( nArg==2 ){
1.4 misho 17738: rc2 = sqlite3_test_control(testctrl);
1.4.2.2 ! misho 17739: isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
1.2 misho 17740: }
17741: break;
17742:
17743: /* sqlite3_test_control(int, uint) */
1.4 misho 17744: case SQLITE_TESTCTRL_PENDING_BYTE:
1.2 misho 17745: if( nArg==3 ){
1.4 misho 17746: unsigned int opt = (unsigned int)integerValue(azArg[2]);
17747: rc2 = sqlite3_test_control(testctrl, opt);
1.4.2.2 ! misho 17748: isOk = 3;
1.2 misho 17749: }
17750: break;
1.4 misho 17751:
1.2 misho 17752: /* sqlite3_test_control(int, int) */
1.4 misho 17753: case SQLITE_TESTCTRL_ASSERT:
17754: case SQLITE_TESTCTRL_ALWAYS:
1.4.2.2 ! misho 17755: case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
1.2 misho 17756: if( nArg==3 ){
1.4 misho 17757: int opt = booleanValue(azArg[2]);
17758: rc2 = sqlite3_test_control(testctrl, opt);
1.4.2.2 ! misho 17759: isOk = 1;
1.2 misho 17760: }
17761: break;
17762:
1.4.2.2 ! misho 17763: /* sqlite3_test_control(int, int) */
! 17764: case SQLITE_TESTCTRL_LOCALTIME_FAULT:
! 17765: case SQLITE_TESTCTRL_NEVER_CORRUPT:
1.2 misho 17766: if( nArg==3 ){
1.4.2.2 ! misho 17767: int opt = booleanValue(azArg[2]);
1.4 misho 17768: rc2 = sqlite3_test_control(testctrl, opt);
1.4.2.2 ! misho 17769: isOk = 3;
1.2 misho 17770: }
17771: break;
17772:
1.4 misho 17773: case SQLITE_TESTCTRL_IMPOSTER:
17774: if( nArg==5 ){
17775: rc2 = sqlite3_test_control(testctrl, p->db,
17776: azArg[2],
17777: integerValue(azArg[3]),
17778: integerValue(azArg[4]));
1.4.2.2 ! misho 17779: isOk = 3;
1.4 misho 17780: }
17781: break;
17782:
1.4.2.2 ! misho 17783: #ifdef YYCOVERAGE
! 17784: case SQLITE_TESTCTRL_PARSER_COVERAGE:
! 17785: if( nArg==2 ){
! 17786: sqlite3_test_control(testctrl, p->out);
! 17787: isOk = 3;
! 17788: }
! 17789: #endif
1.2 misho 17790: }
17791: }
1.4.2.2 ! misho 17792: if( isOk==0 && iCtrl>=0 ){
! 17793: utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
! 17794: rc = 1;
! 17795: }else if( isOk==1 ){
! 17796: raw_printf(p->out, "%d\n", rc2);
! 17797: }else if( isOk==2 ){
! 17798: raw_printf(p->out, "0x%08x\n", rc2);
! 17799: }
1.2 misho 17800: }else
1.4.2.1 misho 17801: #endif /* !defined(SQLITE_UNTESTABLE) */
1.2 misho 17802:
1.4 misho 17803: if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
17804: open_db(p, 0);
17805: sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
17806: }else
17807:
17808: if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
17809: if( nArg==2 ){
17810: enableTimer = booleanValue(azArg[1]);
17811: if( enableTimer && !HAS_TIMER ){
17812: raw_printf(stderr, "Error: timer not available on this system.\n");
17813: enableTimer = 0;
17814: }
17815: }else{
17816: raw_printf(stderr, "Usage: .timer on|off\n");
17817: rc = 1;
17818: }
1.2 misho 17819: }else
1.4 misho 17820:
1.4.2.2 ! misho 17821: #ifndef SQLITE_OMIT_TRACE
1.4 misho 17822: if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
1.4.2.2 ! misho 17823: int mType = 0;
! 17824: int jj;
1.4 misho 17825: open_db(p, 0);
1.4.2.2 ! misho 17826: for(jj=1; jj<nArg; jj++){
! 17827: const char *z = azArg[jj];
! 17828: if( z[0]=='-' ){
! 17829: if( optionMatch(z, "expanded") ){
! 17830: p->eTraceType = SHELL_TRACE_EXPANDED;
! 17831: }
! 17832: #ifdef SQLITE_ENABLE_NORMALIZE
! 17833: else if( optionMatch(z, "normalized") ){
! 17834: p->eTraceType = SHELL_TRACE_NORMALIZED;
! 17835: }
! 17836: #endif
! 17837: else if( optionMatch(z, "plain") ){
! 17838: p->eTraceType = SHELL_TRACE_PLAIN;
! 17839: }
! 17840: else if( optionMatch(z, "profile") ){
! 17841: mType |= SQLITE_TRACE_PROFILE;
! 17842: }
! 17843: else if( optionMatch(z, "row") ){
! 17844: mType |= SQLITE_TRACE_ROW;
! 17845: }
! 17846: else if( optionMatch(z, "stmt") ){
! 17847: mType |= SQLITE_TRACE_STMT;
! 17848: }
! 17849: else if( optionMatch(z, "close") ){
! 17850: mType |= SQLITE_TRACE_CLOSE;
! 17851: }
! 17852: else {
! 17853: raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
! 17854: rc = 1;
! 17855: goto meta_command_exit;
! 17856: }
! 17857: }else{
! 17858: output_file_close(p->traceOut);
! 17859: p->traceOut = output_file_open(azArg[1], 0);
! 17860: }
1.4 misho 17861: }
1.3 misho 17862: if( p->traceOut==0 ){
1.4 misho 17863: sqlite3_trace_v2(p->db, 0, 0, 0);
1.3 misho 17864: }else{
1.4.2.2 ! misho 17865: if( mType==0 ) mType = SQLITE_TRACE_STMT;
! 17866: sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
1.3 misho 17867: }
17868: }else
1.4.2.2 ! misho 17869: #endif /* !defined(SQLITE_OMIT_TRACE) */
1.3 misho 17870:
1.4 misho 17871: #if SQLITE_USER_AUTHENTICATION
17872: if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
17873: if( nArg<2 ){
17874: raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
17875: rc = 1;
17876: goto meta_command_exit;
17877: }
17878: open_db(p, 0);
17879: if( strcmp(azArg[1],"login")==0 ){
17880: if( nArg!=4 ){
17881: raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
17882: rc = 1;
17883: goto meta_command_exit;
17884: }
1.4.2.2 ! misho 17885: rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
1.4 misho 17886: if( rc ){
17887: utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
17888: rc = 1;
17889: }
17890: }else if( strcmp(azArg[1],"add")==0 ){
17891: if( nArg!=5 ){
17892: raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
17893: rc = 1;
17894: goto meta_command_exit;
17895: }
1.4.2.2 ! misho 17896: rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
1.4 misho 17897: booleanValue(azArg[4]));
17898: if( rc ){
17899: raw_printf(stderr, "User-Add failed: %d\n", rc);
17900: rc = 1;
17901: }
17902: }else if( strcmp(azArg[1],"edit")==0 ){
17903: if( nArg!=5 ){
17904: raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
17905: rc = 1;
17906: goto meta_command_exit;
17907: }
1.4.2.2 ! misho 17908: rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
1.4 misho 17909: booleanValue(azArg[4]));
17910: if( rc ){
17911: raw_printf(stderr, "User-Edit failed: %d\n", rc);
17912: rc = 1;
17913: }
17914: }else if( strcmp(azArg[1],"delete")==0 ){
17915: if( nArg!=3 ){
17916: raw_printf(stderr, "Usage: .user delete USER\n");
17917: rc = 1;
17918: goto meta_command_exit;
17919: }
17920: rc = sqlite3_user_delete(p->db, azArg[2]);
17921: if( rc ){
17922: raw_printf(stderr, "User-Delete failed: %d\n", rc);
17923: rc = 1;
17924: }
17925: }else{
17926: raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
17927: rc = 1;
17928: goto meta_command_exit;
17929: }
17930: }else
17931: #endif /* SQLITE_USER_AUTHENTICATION */
17932:
1.2 misho 17933: if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
1.4 misho 17934: utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
1.2 misho 17935: sqlite3_libversion(), sqlite3_sourceid());
1.4.2.2 ! misho 17936: #if SQLITE_HAVE_ZLIB
! 17937: utf8_printf(p->out, "zlib version %s\n", zlibVersion());
! 17938: #endif
! 17939: #define CTIMEOPT_VAL_(opt) #opt
! 17940: #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
! 17941: #if defined(__clang__) && defined(__clang_major__)
! 17942: utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
! 17943: CTIMEOPT_VAL(__clang_minor__) "."
! 17944: CTIMEOPT_VAL(__clang_patchlevel__) "\n");
! 17945: #elif defined(_MSC_VER)
! 17946: utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
! 17947: #elif defined(__GNUC__) && defined(__VERSION__)
! 17948: utf8_printf(p->out, "gcc-" __VERSION__ "\n");
! 17949: #endif
1.2 misho 17950: }else
17951:
1.4 misho 17952: if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
17953: const char *zDbName = nArg==2 ? azArg[1] : "main";
1.4.2.1 misho 17954: sqlite3_vfs *pVfs = 0;
1.4 misho 17955: if( p->db ){
17956: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
17957: if( pVfs ){
17958: utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
17959: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
17960: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
17961: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
17962: }
17963: }
17964: }else
17965:
17966: if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
17967: sqlite3_vfs *pVfs;
17968: sqlite3_vfs *pCurrent = 0;
17969: if( p->db ){
17970: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
17971: }
17972: for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
17973: utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
17974: pVfs==pCurrent ? " <--- CURRENT" : "");
17975: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
17976: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
17977: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
17978: if( pVfs->pNext ){
17979: raw_printf(p->out, "-----------------------------------\n");
17980: }
17981: }
17982: }else
17983:
1.2 misho 17984: if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
17985: const char *zDbName = nArg==2 ? azArg[1] : "main";
17986: char *zVfsName = 0;
17987: if( p->db ){
17988: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
17989: if( zVfsName ){
1.4 misho 17990: utf8_printf(p->out, "%s\n", zVfsName);
1.2 misho 17991: sqlite3_free(zVfsName);
17992: }
17993: }
17994: }else
17995:
1.3 misho 17996: #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
17997: if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
1.4 misho 17998: sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
1.3 misho 17999: }else
18000: #endif
18001:
1.4 misho 18002: if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
1.2 misho 18003: int j;
18004: assert( nArg<=ArraySize(azArg) );
18005: for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
1.4 misho 18006: p->colWidth[j-1] = (int)integerValue(azArg[j]);
1.2 misho 18007: }
18008: }else
18009:
18010: {
1.4 misho 18011: utf8_printf(stderr, "Error: unknown command or invalid arguments: "
1.2 misho 18012: " \"%s\". Enter \".help\" for help\n", azArg[0]);
18013: rc = 1;
18014: }
18015:
1.4 misho 18016: meta_command_exit:
18017: if( p->outCount ){
18018: p->outCount--;
18019: if( p->outCount==0 ) output_reset(p);
18020: }
1.2 misho 18021: return rc;
18022: }
18023:
18024: /*
18025: ** Return TRUE if a semicolon occurs anywhere in the first N characters
18026: ** of string z[].
18027: */
1.4 misho 18028: static int line_contains_semicolon(const char *z, int N){
1.2 misho 18029: int i;
18030: for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
18031: return 0;
18032: }
18033:
18034: /*
18035: ** Test to see if a line consists entirely of whitespace.
18036: */
18037: static int _all_whitespace(const char *z){
18038: for(; *z; z++){
18039: if( IsSpace(z[0]) ) continue;
18040: if( *z=='/' && z[1]=='*' ){
18041: z += 2;
18042: while( *z && (*z!='*' || z[1]!='/') ){ z++; }
18043: if( *z==0 ) return 0;
18044: z++;
18045: continue;
18046: }
18047: if( *z=='-' && z[1]=='-' ){
18048: z += 2;
18049: while( *z && *z!='\n' ){ z++; }
18050: if( *z==0 ) return 1;
18051: continue;
18052: }
18053: return 0;
18054: }
18055: return 1;
18056: }
18057:
18058: /*
18059: ** Return TRUE if the line typed in is an SQL command terminator other
18060: ** than a semi-colon. The SQL Server style "go" command is understood
18061: ** as is the Oracle "/".
18062: */
1.4 misho 18063: static int line_is_command_terminator(const char *zLine){
1.2 misho 18064: while( IsSpace(zLine[0]) ){ zLine++; };
18065: if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
18066: return 1; /* Oracle */
18067: }
18068: if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
18069: && _all_whitespace(&zLine[2]) ){
18070: return 1; /* SQL Server */
18071: }
18072: return 0;
18073: }
18074:
18075: /*
1.4.2.2 ! misho 18076: ** We need a default sqlite3_complete() implementation to use in case
! 18077: ** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
! 18078: ** any arbitrary text is a complete SQL statement. This is not very
! 18079: ** user-friendly, but it does seem to work.
! 18080: */
! 18081: #ifdef SQLITE_OMIT_COMPLETE
! 18082: #define sqlite3_complete(x) 1
! 18083: #endif
! 18084:
! 18085: /*
1.2 misho 18086: ** Return true if zSql is a complete SQL statement. Return false if it
18087: ** ends in the middle of a string literal or C-style comment.
18088: */
1.4 misho 18089: static int line_is_complete(char *zSql, int nSql){
1.2 misho 18090: int rc;
18091: if( zSql==0 ) return 1;
18092: zSql[nSql] = ';';
18093: zSql[nSql+1] = 0;
18094: rc = sqlite3_complete(zSql);
18095: zSql[nSql] = 0;
18096: return rc;
18097: }
18098:
18099: /*
1.4.2.2 ! misho 18100: ** Run a single line of SQL. Return the number of errors.
1.4.2.1 misho 18101: */
18102: static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
18103: int rc;
18104: char *zErrMsg = 0;
18105:
18106: open_db(p, 0);
18107: if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
1.4.2.2 ! misho 18108: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
1.4.2.1 misho 18109: BEGIN_TIMER;
1.4.2.2 ! misho 18110: rc = shell_exec(p, zSql, &zErrMsg);
1.4.2.1 misho 18111: END_TIMER;
18112: if( rc || zErrMsg ){
18113: char zPrefix[100];
18114: if( in!=0 || !stdin_is_interactive ){
18115: sqlite3_snprintf(sizeof(zPrefix), zPrefix,
18116: "Error: near line %d:", startline);
18117: }else{
18118: sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
18119: }
18120: if( zErrMsg!=0 ){
18121: utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
18122: sqlite3_free(zErrMsg);
18123: zErrMsg = 0;
18124: }else{
18125: utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
18126: }
18127: return 1;
18128: }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
18129: raw_printf(p->out, "changes: %3d total_changes: %d\n",
18130: sqlite3_changes(p->db), sqlite3_total_changes(p->db));
18131: }
18132: return 0;
18133: }
18134:
18135:
18136: /*
1.2 misho 18137: ** Read input from *in and process it. If *in==0 then input
18138: ** is interactive - the user is typing it it. Otherwise, input
18139: ** is coming from a file or device. A prompt is issued and history
18140: ** is saved only if input is interactive. An interrupt signal will
18141: ** cause this routine to exit immediately, unless input is interactive.
18142: **
18143: ** Return the number of errors.
18144: */
1.4.2.2 ! misho 18145: static int process_input(ShellState *p){
1.4 misho 18146: char *zLine = 0; /* A single input line */
18147: char *zSql = 0; /* Accumulated SQL text */
18148: int nLine; /* Length of current line */
18149: int nSql = 0; /* Bytes of zSql[] used */
18150: int nAlloc = 0; /* Allocated zSql[] space */
18151: int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
18152: int rc; /* Error code */
18153: int errCnt = 0; /* Number of errors seen */
18154: int startline = 0; /* Line number for start of current input */
1.2 misho 18155:
1.4.2.2 ! misho 18156: p->lineno = 0;
! 18157: while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
1.2 misho 18158: fflush(p->out);
1.4.2.2 ! misho 18159: zLine = one_input_line(p->in, zLine, nSql>0);
1.2 misho 18160: if( zLine==0 ){
1.3 misho 18161: /* End of input */
1.4.2.2 ! misho 18162: if( p->in==0 && stdin_is_interactive ) printf("\n");
1.3 misho 18163: break;
1.2 misho 18164: }
18165: if( seenInterrupt ){
1.4.2.2 ! misho 18166: if( p->in!=0 ) break;
1.2 misho 18167: seenInterrupt = 0;
18168: }
1.4.2.2 ! misho 18169: p->lineno++;
1.4 misho 18170: if( nSql==0 && _all_whitespace(zLine) ){
1.4.2.1 misho 18171: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
1.4 misho 18172: continue;
18173: }
1.4.2.2 ! misho 18174: if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
1.4.2.1 misho 18175: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
1.4.2.2 ! misho 18176: if( zLine[0]=='.' ){
! 18177: rc = do_meta_command(zLine, p);
! 18178: if( rc==2 ){ /* exit requested */
! 18179: break;
! 18180: }else if( rc ){
! 18181: errCnt++;
! 18182: }
1.2 misho 18183: }
18184: continue;
18185: }
1.4 misho 18186: if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
1.2 misho 18187: memcpy(zLine,";",2);
18188: }
1.4 misho 18189: nLine = strlen30(zLine);
18190: if( nSql+nLine+2>=nAlloc ){
18191: nAlloc = nSql+nLine+100;
18192: zSql = realloc(zSql, nAlloc);
1.4.2.2 ! misho 18193: if( zSql==0 ) shell_out_of_memory();
1.4 misho 18194: }
1.2 misho 18195: nSqlPrior = nSql;
1.4 misho 18196: if( nSql==0 ){
1.2 misho 18197: int i;
18198: for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
1.4 misho 18199: assert( nAlloc>0 && zSql!=0 );
18200: memcpy(zSql, zLine+i, nLine+1-i);
1.4.2.2 ! misho 18201: startline = p->lineno;
1.4 misho 18202: nSql = nLine-i;
1.2 misho 18203: }else{
18204: zSql[nSql++] = '\n';
1.4 misho 18205: memcpy(zSql+nSql, zLine, nLine+1);
18206: nSql += nLine;
1.2 misho 18207: }
1.4 misho 18208: if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
1.2 misho 18209: && sqlite3_complete(zSql) ){
1.4.2.2 ! misho 18210: errCnt += runOneSqlLine(p, zSql, p->in, startline);
1.4 misho 18211: nSql = 0;
18212: if( p->outCount ){
18213: output_reset(p);
18214: p->outCount = 0;
1.4.2.2 ! misho 18215: }else{
! 18216: clearTempFile(p);
1.4 misho 18217: }
18218: }else if( nSql && _all_whitespace(zSql) ){
1.4.2.1 misho 18219: if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
1.2 misho 18220: nSql = 0;
18221: }
18222: }
1.4.2.1 misho 18223: if( nSql && !_all_whitespace(zSql) ){
1.4.2.2 ! misho 18224: errCnt += runOneSqlLine(p, zSql, p->in, startline);
1.2 misho 18225: }
1.4 misho 18226: free(zSql);
1.2 misho 18227: free(zLine);
1.3 misho 18228: return errCnt>0;
1.2 misho 18229: }
18230:
18231: /*
18232: ** Return a pathname which is the user's home directory. A
1.3 misho 18233: ** 0 return indicates an error of some kind.
1.2 misho 18234: */
1.4.2.1 misho 18235: static char *find_home_dir(int clearFlag){
1.3 misho 18236: static char *home_dir = NULL;
1.4.2.1 misho 18237: if( clearFlag ){
18238: free(home_dir);
18239: home_dir = 0;
18240: return 0;
18241: }
1.3 misho 18242: if( home_dir ) return home_dir;
1.2 misho 18243:
1.4 misho 18244: #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
18245: && !defined(__RTP__) && !defined(_WRS_KERNEL)
1.3 misho 18246: {
18247: struct passwd *pwent;
18248: uid_t uid = getuid();
18249: if( (pwent=getpwuid(uid)) != NULL) {
18250: home_dir = pwent->pw_dir;
18251: }
1.2 misho 18252: }
18253: #endif
18254:
18255: #if defined(_WIN32_WCE)
18256: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
18257: */
1.3 misho 18258: home_dir = "/";
1.2 misho 18259: #else
18260:
1.3 misho 18261: #if defined(_WIN32) || defined(WIN32)
1.2 misho 18262: if (!home_dir) {
18263: home_dir = getenv("USERPROFILE");
18264: }
18265: #endif
18266:
18267: if (!home_dir) {
18268: home_dir = getenv("HOME");
18269: }
18270:
1.3 misho 18271: #if defined(_WIN32) || defined(WIN32)
1.2 misho 18272: if (!home_dir) {
18273: char *zDrive, *zPath;
18274: int n;
18275: zDrive = getenv("HOMEDRIVE");
18276: zPath = getenv("HOMEPATH");
18277: if( zDrive && zPath ){
18278: n = strlen30(zDrive) + strlen30(zPath) + 1;
18279: home_dir = malloc( n );
18280: if( home_dir==0 ) return 0;
18281: sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
18282: return home_dir;
18283: }
18284: home_dir = "c:\\";
18285: }
18286: #endif
18287:
18288: #endif /* !_WIN32_WCE */
18289:
18290: if( home_dir ){
18291: int n = strlen30(home_dir) + 1;
18292: char *z = malloc( n );
18293: if( z ) memcpy(z, home_dir, n);
18294: home_dir = z;
18295: }
18296:
18297: return home_dir;
18298: }
18299:
18300: /*
18301: ** Read input from the file given by sqliterc_override. Or if that
18302: ** parameter is NULL, take input from ~/.sqliterc
18303: **
18304: ** Returns the number of errors.
18305: */
1.4 misho 18306: static void process_sqliterc(
18307: ShellState *p, /* Configuration data */
1.2 misho 18308: const char *sqliterc_override /* Name of config file. NULL to use default */
18309: ){
18310: char *home_dir = NULL;
18311: const char *sqliterc = sqliterc_override;
18312: char *zBuf = 0;
1.4.2.2 ! misho 18313: FILE *inSaved = p->in;
! 18314: int savedLineno = p->lineno;
1.2 misho 18315:
18316: if (sqliterc == NULL) {
1.4.2.1 misho 18317: home_dir = find_home_dir(0);
1.2 misho 18318: if( home_dir==0 ){
1.4 misho 18319: raw_printf(stderr, "-- warning: cannot find home directory;"
18320: " cannot read ~/.sqliterc\n");
18321: return;
1.2 misho 18322: }
1.3 misho 18323: zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
18324: sqliterc = zBuf;
1.2 misho 18325: }
1.4.2.2 ! misho 18326: p->in = fopen(sqliterc,"rb");
! 18327: if( p->in ){
1.2 misho 18328: if( stdin_is_interactive ){
1.4 misho 18329: utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
1.2 misho 18330: }
1.4.2.2 ! misho 18331: process_input(p);
! 18332: fclose(p->in);
1.2 misho 18333: }
1.4.2.2 ! misho 18334: p->in = inSaved;
! 18335: p->lineno = savedLineno;
1.3 misho 18336: sqlite3_free(zBuf);
1.2 misho 18337: }
18338:
18339: /*
18340: ** Show available command line options
18341: */
1.4 misho 18342: static const char zOptions[] =
1.4.2.2 ! misho 18343: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
! 18344: " -A ARGS... run \".archive ARGS\" and exit\n"
! 18345: #endif
! 18346: " -append append the database to the end of the file\n"
1.4 misho 18347: " -ascii set output mode to 'ascii'\n"
1.2 misho 18348: " -bail stop after hitting an error\n"
18349: " -batch force batch I/O\n"
18350: " -column set output mode to 'column'\n"
1.3 misho 18351: " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
1.2 misho 18352: " -csv set output mode to 'csv'\n"
1.4.2.2 ! misho 18353: #if defined(SQLITE_ENABLE_DESERIALIZE)
! 18354: " -deserialize open the database using sqlite3_deserialize()\n"
! 18355: #endif
1.3 misho 18356: " -echo print commands before execution\n"
18357: " -init FILENAME read/process named file\n"
18358: " -[no]header turn headers on or off\n"
18359: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
18360: " -heap SIZE Size of heap for memsys3 or memsys5\n"
18361: #endif
18362: " -help show this message\n"
1.2 misho 18363: " -html set output mode to HTML\n"
1.3 misho 18364: " -interactive force interactive I/O\n"
1.2 misho 18365: " -line set output mode to 'line'\n"
18366: " -list set output mode to 'list'\n"
1.4 misho 18367: " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
1.4.2.2 ! misho 18368: #if defined(SQLITE_ENABLE_DESERIALIZE)
! 18369: " -maxsize N maximum size for a --deserialize database\n"
! 18370: #endif
! 18371: " -memtrace trace all memory allocations and deallocations\n"
1.4 misho 18372: " -mmap N default mmap size set to N\n"
1.3 misho 18373: #ifdef SQLITE_ENABLE_MULTIPLEX
18374: " -multiplex enable the multiplexor VFS\n"
18375: #endif
1.4 misho 18376: " -newline SEP set output row separator. Default: '\\n'\n"
1.3 misho 18377: " -nullvalue TEXT set text string for NULL values. Default ''\n"
1.4 misho 18378: " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
1.4.2.2 ! misho 18379: " -quote set output mode to 'quote'\n"
! 18380: " -readonly open the database read-only\n"
1.4 misho 18381: " -separator SEP set output column separator. Default: '|'\n"
1.4.2.2 ! misho 18382: #ifdef SQLITE_ENABLE_SORTER_REFERENCES
! 18383: " -sorterref SIZE sorter references threshold size\n"
! 18384: #endif
1.2 misho 18385: " -stats print memory stats before each finalize\n"
18386: " -version show SQLite version\n"
18387: " -vfs NAME use NAME as the default VFS\n"
18388: #ifdef SQLITE_ENABLE_VFSTRACE
18389: " -vfstrace enable tracing of all VFS calls\n"
18390: #endif
1.4.2.2 ! misho 18391: #ifdef SQLITE_HAVE_ZLIB
! 18392: " -zip open the file as a ZIP Archive\n"
! 18393: #endif
1.2 misho 18394: ;
18395: static void usage(int showDetail){
1.4 misho 18396: utf8_printf(stderr,
18397: "Usage: %s [OPTIONS] FILENAME [SQL]\n"
1.2 misho 18398: "FILENAME is the name of an SQLite database. A new database is created\n"
18399: "if the file does not previously exist.\n", Argv0);
18400: if( showDetail ){
1.4 misho 18401: utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
1.2 misho 18402: }else{
1.4 misho 18403: raw_printf(stderr, "Use the -help option for additional information\n");
1.2 misho 18404: }
18405: exit(1);
18406: }
18407:
18408: /*
1.4.2.2 ! misho 18409: ** Internal check: Verify that the SQLite is uninitialized. Print a
! 18410: ** error message if it is initialized.
! 18411: */
! 18412: static void verify_uninitialized(void){
! 18413: if( sqlite3_config(-1)==SQLITE_MISUSE ){
! 18414: utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
! 18415: " initialization.\n");
! 18416: }
! 18417: }
! 18418:
! 18419: /*
1.2 misho 18420: ** Initialize the state information in data
18421: */
1.4 misho 18422: static void main_init(ShellState *data) {
1.2 misho 18423: memset(data, 0, sizeof(*data));
1.4 misho 18424: data->normalMode = data->cMode = data->mode = MODE_List;
18425: data->autoExplain = 1;
18426: memcpy(data->colSeparator,SEP_Column, 2);
18427: memcpy(data->rowSeparator,SEP_Row, 2);
1.2 misho 18428: data->showHeader = 0;
1.4 misho 18429: data->shellFlgs = SHFLG_Lookaside;
1.4.2.2 ! misho 18430: verify_uninitialized();
1.2 misho 18431: sqlite3_config(SQLITE_CONFIG_URI, 1);
18432: sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
1.4 misho 18433: sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
1.2 misho 18434: sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
18435: sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
18436: }
18437:
1.3 misho 18438: /*
1.4 misho 18439: ** Output text to the console in a font that attracts extra attention.
18440: */
18441: #ifdef _WIN32
18442: static void printBold(const char *zText){
18443: HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
18444: CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
18445: GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
18446: SetConsoleTextAttribute(out,
18447: FOREGROUND_RED|FOREGROUND_INTENSITY
18448: );
18449: printf("%s", zText);
18450: SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
18451: }
18452: #else
18453: static void printBold(const char *zText){
18454: printf("\033[1m%s\033[0m", zText);
18455: }
18456: #endif
18457:
18458: /*
1.3 misho 18459: ** Get the argument to an --option. Throw an error and die if no argument
18460: ** is available.
18461: */
18462: static char *cmdline_option_value(int argc, char **argv, int i){
18463: if( i==argc ){
1.4 misho 18464: utf8_printf(stderr, "%s: Error: missing argument to %s\n",
1.3 misho 18465: argv[0], argv[argc-1]);
18466: exit(1);
18467: }
18468: return argv[i];
18469: }
18470:
1.4 misho 18471: #ifndef SQLITE_SHELL_IS_UTF8
18472: # if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
18473: # define SQLITE_SHELL_IS_UTF8 (0)
18474: # else
18475: # define SQLITE_SHELL_IS_UTF8 (1)
18476: # endif
18477: #endif
18478:
18479: #if SQLITE_SHELL_IS_UTF8
18480: int SQLITE_CDECL main(int argc, char **argv){
18481: #else
18482: int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
18483: char **argv;
18484: #endif
1.2 misho 18485: char *zErrMsg = 0;
1.4 misho 18486: ShellState data;
1.2 misho 18487: const char *zInitFile = 0;
18488: int i;
18489: int rc = 0;
1.4 misho 18490: int warnInmemoryDb = 0;
18491: int readStdin = 1;
18492: int nCmd = 0;
18493: char **azCmd = 0;
1.4.2.2 ! misho 18494: const char *zVfs = 0; /* Value of -vfs command-line option */
! 18495: #if !SQLITE_SHELL_IS_UTF8
! 18496: char **argvToFree = 0;
! 18497: int argcToFree = 0;
! 18498: #endif
1.4 misho 18499:
18500: setBinaryMode(stdin, 0);
18501: setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
18502: stdin_is_interactive = isatty(0);
18503: stdout_is_console = isatty(1);
1.2 misho 18504:
1.4.2.2 ! misho 18505: #if !defined(_WIN32_WCE)
! 18506: if( getenv("SQLITE_DEBUG_BREAK") ){
! 18507: if( isatty(0) && isatty(2) ){
! 18508: fprintf(stderr,
! 18509: "attach debugger to process %d and press any key to continue.\n",
! 18510: GETPID());
! 18511: fgetc(stdin);
! 18512: }else{
! 18513: #if defined(_WIN32) || defined(WIN32)
! 18514: DebugBreak();
! 18515: #elif defined(SIGTRAP)
! 18516: raise(SIGTRAP);
! 18517: #endif
! 18518: }
! 18519: }
! 18520: #endif
! 18521:
1.4 misho 18522: #if USE_SYSTEM_SQLITE+0!=1
1.4.2.2 ! misho 18523: if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
1.4 misho 18524: utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
1.2 misho 18525: sqlite3_sourceid(), SQLITE_SOURCE_ID);
18526: exit(1);
18527: }
1.4 misho 18528: #endif
18529: main_init(&data);
1.4.2.2 ! misho 18530:
! 18531: /* On Windows, we must translate command-line arguments into UTF-8.
! 18532: ** The SQLite memory allocator subsystem has to be enabled in order to
! 18533: ** do this. But we want to run an sqlite3_shutdown() afterwards so that
! 18534: ** subsequent sqlite3_config() calls will work. So copy all results into
! 18535: ** memory that does not come from the SQLite memory allocator.
! 18536: */
1.4 misho 18537: #if !SQLITE_SHELL_IS_UTF8
18538: sqlite3_initialize();
1.4.2.2 ! misho 18539: argvToFree = malloc(sizeof(argv[0])*argc*2);
! 18540: argcToFree = argc;
! 18541: argv = argvToFree + argc;
! 18542: if( argv==0 ) shell_out_of_memory();
1.4 misho 18543: for(i=0; i<argc; i++){
1.4.2.2 ! misho 18544: char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
! 18545: int n;
! 18546: if( z==0 ) shell_out_of_memory();
! 18547: n = (int)strlen(z);
! 18548: argv[i] = malloc( n+1 );
! 18549: if( argv[i]==0 ) shell_out_of_memory();
! 18550: memcpy(argv[i], z, n+1);
! 18551: argvToFree[i] = argv[i];
! 18552: sqlite3_free(z);
1.4 misho 18553: }
1.4.2.2 ! misho 18554: sqlite3_shutdown();
1.4 misho 18555: #endif
1.4.2.2 ! misho 18556:
1.4 misho 18557: assert( argc>=1 && argv && argv[0] );
1.2 misho 18558: Argv0 = argv[0];
18559:
18560: /* Make sure we have a valid signal handler early, before anything
18561: ** else is done.
18562: */
18563: #ifdef SIGINT
18564: signal(SIGINT, interrupt_handler);
1.4.2.2 ! misho 18565: #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
! 18566: SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
1.2 misho 18567: #endif
18568:
1.4 misho 18569: #ifdef SQLITE_SHELL_DBNAME_PROC
18570: {
18571: /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
18572: ** of a C-function that will provide the name of the database file. Use
18573: ** this compile-time option to embed this shell program in larger
18574: ** applications. */
18575: extern void SQLITE_SHELL_DBNAME_PROC(const char**);
18576: SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
18577: warnInmemoryDb = 0;
18578: }
18579: #endif
18580:
1.2 misho 18581: /* Do an initial pass through the command-line argument to locate
18582: ** the name of the database file, the name of the initialization file,
18583: ** the size of the alternative malloc heap,
18584: ** and the first command to execute.
18585: */
1.4.2.2 ! misho 18586: verify_uninitialized();
1.3 misho 18587: for(i=1; i<argc; i++){
1.2 misho 18588: char *z;
18589: z = argv[i];
1.3 misho 18590: if( z[0]!='-' ){
18591: if( data.zDbFilename==0 ){
18592: data.zDbFilename = z;
1.4 misho 18593: }else{
18594: /* Excesss arguments are interpreted as SQL (or dot-commands) and
18595: ** mean that nothing is read from stdin */
18596: readStdin = 0;
18597: nCmd++;
18598: azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
1.4.2.2 ! misho 18599: if( azCmd==0 ) shell_out_of_memory();
1.4 misho 18600: azCmd[nCmd-1] = z;
1.3 misho 18601: }
18602: }
18603: if( z[1]=='-' ) z++;
18604: if( strcmp(z,"-separator")==0
18605: || strcmp(z,"-nullvalue")==0
1.4 misho 18606: || strcmp(z,"-newline")==0
1.3 misho 18607: || strcmp(z,"-cmd")==0
18608: ){
18609: (void)cmdline_option_value(argc, argv, ++i);
18610: }else if( strcmp(z,"-init")==0 ){
18611: zInitFile = cmdline_option_value(argc, argv, ++i);
18612: }else if( strcmp(z,"-batch")==0 ){
18613: /* Need to check for batch mode here to so we can avoid printing
1.4 misho 18614: ** informational messages (like from process_sqliterc) before
1.3 misho 18615: ** we do the actual processing of arguments later in a second pass.
18616: */
1.2 misho 18617: stdin_is_interactive = 0;
1.3 misho 18618: }else if( strcmp(z,"-heap")==0 ){
1.2 misho 18619: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
18620: const char *zSize;
18621: sqlite3_int64 szHeap;
18622:
1.3 misho 18623: zSize = cmdline_option_value(argc, argv, ++i);
1.4 misho 18624: szHeap = integerValue(zSize);
1.2 misho 18625: if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
18626: sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
1.4 misho 18627: #else
18628: (void)cmdline_option_value(argc, argv, ++i);
1.2 misho 18629: #endif
1.4 misho 18630: }else if( strcmp(z,"-pagecache")==0 ){
18631: int n, sz;
18632: sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
18633: if( sz>70000 ) sz = 70000;
18634: if( sz<0 ) sz = 0;
18635: n = (int)integerValue(cmdline_option_value(argc,argv,++i));
18636: sqlite3_config(SQLITE_CONFIG_PAGECACHE,
18637: (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
18638: data.shellFlgs |= SHFLG_Pagecache;
18639: }else if( strcmp(z,"-lookaside")==0 ){
18640: int n, sz;
18641: sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
18642: if( sz<0 ) sz = 0;
18643: n = (int)integerValue(cmdline_option_value(argc,argv,++i));
18644: if( n<0 ) n = 0;
18645: sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
18646: if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
1.2 misho 18647: #ifdef SQLITE_ENABLE_VFSTRACE
1.3 misho 18648: }else if( strcmp(z,"-vfstrace")==0 ){
1.2 misho 18649: extern int vfstrace_register(
18650: const char *zTraceName,
18651: const char *zOldVfsName,
18652: int (*xOut)(const char*,void*),
18653: void *pOutArg,
18654: int makeDefault
18655: );
18656: vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
18657: #endif
18658: #ifdef SQLITE_ENABLE_MULTIPLEX
1.3 misho 18659: }else if( strcmp(z,"-multiplex")==0 ){
1.2 misho 18660: extern int sqlite3_multiple_initialize(const char*,int);
18661: sqlite3_multiplex_initialize(0, 1);
18662: #endif
1.4 misho 18663: }else if( strcmp(z,"-mmap")==0 ){
18664: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
18665: sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
1.4.2.2 ! misho 18666: #ifdef SQLITE_ENABLE_SORTER_REFERENCES
! 18667: }else if( strcmp(z,"-sorterref")==0 ){
! 18668: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
! 18669: sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
! 18670: #endif
1.3 misho 18671: }else if( strcmp(z,"-vfs")==0 ){
1.4.2.2 ! misho 18672: zVfs = cmdline_option_value(argc, argv, ++i);
! 18673: #ifdef SQLITE_HAVE_ZLIB
! 18674: }else if( strcmp(z,"-zip")==0 ){
! 18675: data.openMode = SHELL_OPEN_ZIPFILE;
! 18676: #endif
! 18677: }else if( strcmp(z,"-append")==0 ){
! 18678: data.openMode = SHELL_OPEN_APPENDVFS;
! 18679: #ifdef SQLITE_ENABLE_DESERIALIZE
! 18680: }else if( strcmp(z,"-deserialize")==0 ){
! 18681: data.openMode = SHELL_OPEN_DESERIALIZE;
! 18682: }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
! 18683: data.szMax = integerValue(argv[++i]);
! 18684: #endif
! 18685: }else if( strcmp(z,"-readonly")==0 ){
! 18686: data.openMode = SHELL_OPEN_READONLY;
! 18687: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
! 18688: }else if( strncmp(z, "-A",2)==0 ){
! 18689: /* All remaining command-line arguments are passed to the ".archive"
! 18690: ** command, so ignore them */
! 18691: break;
! 18692: #endif
! 18693: }else if( strcmp(z, "-memtrace")==0 ){
! 18694: sqlite3MemTraceActivate(stderr);
! 18695: }
! 18696: }
! 18697: verify_uninitialized();
! 18698:
! 18699:
! 18700: #ifdef SQLITE_SHELL_INIT_PROC
! 18701: {
! 18702: /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
! 18703: ** of a C-function that will perform initialization actions on SQLite that
! 18704: ** occur just before or after sqlite3_initialize(). Use this compile-time
! 18705: ** option to embed this shell program in larger applications. */
! 18706: extern void SQLITE_SHELL_INIT_PROC(void);
! 18707: SQLITE_SHELL_INIT_PROC();
! 18708: }
! 18709: #else
! 18710: /* All the sqlite3_config() calls have now been made. So it is safe
! 18711: ** to call sqlite3_initialize() and process any command line -vfs option. */
! 18712: sqlite3_initialize();
! 18713: #endif
! 18714:
! 18715: if( zVfs ){
! 18716: sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
! 18717: if( pVfs ){
! 18718: sqlite3_vfs_register(pVfs, 1);
! 18719: }else{
! 18720: utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
! 18721: exit(1);
1.2 misho 18722: }
18723: }
1.4.2.2 ! misho 18724:
1.3 misho 18725: if( data.zDbFilename==0 ){
1.2 misho 18726: #ifndef SQLITE_OMIT_MEMORYDB
18727: data.zDbFilename = ":memory:";
1.4 misho 18728: warnInmemoryDb = argc==1;
1.2 misho 18729: #else
1.4 misho 18730: utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
1.3 misho 18731: return 1;
1.2 misho 18732: #endif
18733: }
18734: data.out = stdout;
1.4.2.2 ! misho 18735: sqlite3_appendvfs_init(0,0,0);
1.2 misho 18736:
18737: /* Go ahead and open the database file if it already exists. If the
18738: ** file does not exist, delay opening it. This prevents empty database
18739: ** files from being created if a user mistypes the database name argument
18740: ** to the sqlite command-line tool.
18741: */
18742: if( access(data.zDbFilename, 0)==0 ){
1.4 misho 18743: open_db(&data, 0);
1.2 misho 18744: }
18745:
18746: /* Process the initialization file if there is one. If no -init option
18747: ** is given on the command line, look for a file named ~/.sqliterc and
18748: ** try to process it.
18749: */
1.4 misho 18750: process_sqliterc(&data,zInitFile);
1.2 misho 18751:
18752: /* Make a second pass through the command-line argument and set
18753: ** options. This second pass is delayed until after the initialization
18754: ** file is processed so that the command-line arguments will override
18755: ** settings in the initialization file.
18756: */
1.3 misho 18757: for(i=1; i<argc; i++){
1.2 misho 18758: char *z = argv[i];
1.3 misho 18759: if( z[0]!='-' ) continue;
1.2 misho 18760: if( z[1]=='-' ){ z++; }
18761: if( strcmp(z,"-init")==0 ){
18762: i++;
18763: }else if( strcmp(z,"-html")==0 ){
18764: data.mode = MODE_Html;
18765: }else if( strcmp(z,"-list")==0 ){
18766: data.mode = MODE_List;
1.4.2.2 ! misho 18767: }else if( strcmp(z,"-quote")==0 ){
! 18768: data.mode = MODE_Quote;
1.2 misho 18769: }else if( strcmp(z,"-line")==0 ){
18770: data.mode = MODE_Line;
18771: }else if( strcmp(z,"-column")==0 ){
18772: data.mode = MODE_Column;
18773: }else if( strcmp(z,"-csv")==0 ){
18774: data.mode = MODE_Csv;
1.4 misho 18775: memcpy(data.colSeparator,",",2);
1.4.2.2 ! misho 18776: #ifdef SQLITE_HAVE_ZLIB
! 18777: }else if( strcmp(z,"-zip")==0 ){
! 18778: data.openMode = SHELL_OPEN_ZIPFILE;
! 18779: #endif
! 18780: }else if( strcmp(z,"-append")==0 ){
! 18781: data.openMode = SHELL_OPEN_APPENDVFS;
! 18782: #ifdef SQLITE_ENABLE_DESERIALIZE
! 18783: }else if( strcmp(z,"-deserialize")==0 ){
! 18784: data.openMode = SHELL_OPEN_DESERIALIZE;
! 18785: }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
! 18786: data.szMax = integerValue(argv[++i]);
! 18787: #endif
! 18788: }else if( strcmp(z,"-readonly")==0 ){
! 18789: data.openMode = SHELL_OPEN_READONLY;
1.4 misho 18790: }else if( strcmp(z,"-ascii")==0 ){
18791: data.mode = MODE_Ascii;
18792: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
18793: SEP_Unit);
18794: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
18795: SEP_Record);
1.2 misho 18796: }else if( strcmp(z,"-separator")==0 ){
1.4 misho 18797: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
18798: "%s",cmdline_option_value(argc,argv,++i));
18799: }else if( strcmp(z,"-newline")==0 ){
18800: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
1.3 misho 18801: "%s",cmdline_option_value(argc,argv,++i));
1.2 misho 18802: }else if( strcmp(z,"-nullvalue")==0 ){
1.4 misho 18803: sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
1.3 misho 18804: "%s",cmdline_option_value(argc,argv,++i));
1.2 misho 18805: }else if( strcmp(z,"-header")==0 ){
18806: data.showHeader = 1;
18807: }else if( strcmp(z,"-noheader")==0 ){
18808: data.showHeader = 0;
18809: }else if( strcmp(z,"-echo")==0 ){
1.4.2.1 misho 18810: ShellSetFlag(&data, SHFLG_Echo);
1.4 misho 18811: }else if( strcmp(z,"-eqp")==0 ){
1.4.2.2 ! misho 18812: data.autoEQP = AUTOEQP_on;
1.4 misho 18813: }else if( strcmp(z,"-eqpfull")==0 ){
1.4.2.2 ! misho 18814: data.autoEQP = AUTOEQP_full;
1.2 misho 18815: }else if( strcmp(z,"-stats")==0 ){
18816: data.statsOn = 1;
1.4 misho 18817: }else if( strcmp(z,"-scanstats")==0 ){
18818: data.scanstatsOn = 1;
18819: }else if( strcmp(z,"-backslash")==0 ){
18820: /* Undocumented command-line option: -backslash
18821: ** Causes C-style backslash escapes to be evaluated in SQL statements
18822: ** prior to sending the SQL into SQLite. Useful for injecting
18823: ** crazy bytes in the middle of SQL statements for testing and debugging.
18824: */
1.4.2.1 misho 18825: ShellSetFlag(&data, SHFLG_Backslash);
1.2 misho 18826: }else if( strcmp(z,"-bail")==0 ){
18827: bail_on_error = 1;
18828: }else if( strcmp(z,"-version")==0 ){
18829: printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
18830: return 0;
18831: }else if( strcmp(z,"-interactive")==0 ){
18832: stdin_is_interactive = 1;
18833: }else if( strcmp(z,"-batch")==0 ){
18834: stdin_is_interactive = 0;
18835: }else if( strcmp(z,"-heap")==0 ){
18836: i++;
1.4 misho 18837: }else if( strcmp(z,"-pagecache")==0 ){
18838: i+=2;
18839: }else if( strcmp(z,"-lookaside")==0 ){
18840: i+=2;
18841: }else if( strcmp(z,"-mmap")==0 ){
18842: i++;
1.4.2.2 ! misho 18843: }else if( strcmp(z,"-memtrace")==0 ){
! 18844: i++;
! 18845: #ifdef SQLITE_ENABLE_SORTER_REFERENCES
! 18846: }else if( strcmp(z,"-sorterref")==0 ){
! 18847: i++;
! 18848: #endif
1.2 misho 18849: }else if( strcmp(z,"-vfs")==0 ){
18850: i++;
18851: #ifdef SQLITE_ENABLE_VFSTRACE
18852: }else if( strcmp(z,"-vfstrace")==0 ){
18853: i++;
18854: #endif
18855: #ifdef SQLITE_ENABLE_MULTIPLEX
18856: }else if( strcmp(z,"-multiplex")==0 ){
18857: i++;
18858: #endif
1.3 misho 18859: }else if( strcmp(z,"-help")==0 ){
1.2 misho 18860: usage(1);
1.3 misho 18861: }else if( strcmp(z,"-cmd")==0 ){
1.4 misho 18862: /* Run commands that follow -cmd first and separately from commands
18863: ** that simply appear on the command-line. This seems goofy. It would
18864: ** be better if all commands ran in the order that they appear. But
18865: ** we retain the goofy behavior for historical compatibility. */
1.3 misho 18866: if( i==argc-1 ) break;
18867: z = cmdline_option_value(argc,argv,++i);
18868: if( z[0]=='.' ){
18869: rc = do_meta_command(z, &data);
1.4 misho 18870: if( rc && bail_on_error ) return rc==2 ? 0 : rc;
1.3 misho 18871: }else{
1.4 misho 18872: open_db(&data, 0);
1.4.2.2 ! misho 18873: rc = shell_exec(&data, z, &zErrMsg);
1.3 misho 18874: if( zErrMsg!=0 ){
1.4 misho 18875: utf8_printf(stderr,"Error: %s\n", zErrMsg);
1.3 misho 18876: if( bail_on_error ) return rc!=0 ? rc : 1;
18877: }else if( rc!=0 ){
1.4 misho 18878: utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
1.3 misho 18879: if( bail_on_error ) return rc;
18880: }
18881: }
1.4.2.2 ! misho 18882: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
! 18883: }else if( strncmp(z, "-A", 2)==0 ){
! 18884: if( nCmd>0 ){
! 18885: utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
! 18886: " with \"%s\"\n", z);
! 18887: return 1;
! 18888: }
! 18889: open_db(&data, OPEN_DB_ZIPFILE);
! 18890: if( z[2] ){
! 18891: argv[i] = &z[2];
! 18892: arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
! 18893: }else{
! 18894: arDotCommand(&data, 1, argv+i, argc-i);
! 18895: }
! 18896: readStdin = 0;
! 18897: break;
! 18898: #endif
1.2 misho 18899: }else{
1.4 misho 18900: utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
18901: raw_printf(stderr,"Use -help for a list of options.\n");
1.2 misho 18902: return 1;
18903: }
1.4 misho 18904: data.cMode = data.mode;
1.2 misho 18905: }
18906:
1.4 misho 18907: if( !readStdin ){
18908: /* Run all arguments that do not begin with '-' as if they were separate
18909: ** command-line inputs, except for the argToSkip argument which contains
18910: ** the database filename.
1.2 misho 18911: */
1.4 misho 18912: for(i=0; i<nCmd; i++){
18913: if( azCmd[i][0]=='.' ){
18914: rc = do_meta_command(azCmd[i], &data);
18915: if( rc ) return rc==2 ? 0 : rc;
18916: }else{
18917: open_db(&data, 0);
1.4.2.2 ! misho 18918: rc = shell_exec(&data, azCmd[i], &zErrMsg);
1.4 misho 18919: if( zErrMsg!=0 ){
18920: utf8_printf(stderr,"Error: %s\n", zErrMsg);
18921: return rc!=0 ? rc : 1;
18922: }else if( rc!=0 ){
18923: utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
18924: return rc;
18925: }
1.2 misho 18926: }
18927: }
1.4 misho 18928: free(azCmd);
1.2 misho 18929: }else{
18930: /* Run commands received from standard input
18931: */
18932: if( stdin_is_interactive ){
18933: char *zHome;
1.4.2.2 ! misho 18934: char *zHistory;
1.2 misho 18935: int nHistory;
18936: printf(
18937: "SQLite version %s %.19s\n" /*extra-version-info*/
1.4 misho 18938: "Enter \".help\" for usage hints.\n",
1.2 misho 18939: sqlite3_libversion(), sqlite3_sourceid()
18940: );
1.4 misho 18941: if( warnInmemoryDb ){
18942: printf("Connected to a ");
18943: printBold("transient in-memory database");
18944: printf(".\nUse \".open FILENAME\" to reopen on a "
18945: "persistent database.\n");
18946: }
1.4.2.2 ! misho 18947: zHistory = getenv("SQLITE_HISTORY");
! 18948: if( zHistory ){
! 18949: zHistory = strdup(zHistory);
! 18950: }else if( (zHome = find_home_dir(0))!=0 ){
1.2 misho 18951: nHistory = strlen30(zHome) + 20;
18952: if( (zHistory = malloc(nHistory))!=0 ){
18953: sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
18954: }
18955: }
1.4 misho 18956: if( zHistory ){ shell_read_history(zHistory); }
1.4.2.2 ! misho 18957: #if HAVE_READLINE || HAVE_EDITLINE
! 18958: rl_attempted_completion_function = readline_completion;
! 18959: #elif HAVE_LINENOISE
! 18960: linenoiseSetCompletionCallback(linenoise_completion);
! 18961: #endif
! 18962: data.in = 0;
! 18963: rc = process_input(&data);
1.2 misho 18964: if( zHistory ){
1.4.2.2 ! misho 18965: shell_stifle_history(2000);
1.4 misho 18966: shell_write_history(zHistory);
1.2 misho 18967: free(zHistory);
18968: }
18969: }else{
1.4.2.2 ! misho 18970: data.in = stdin;
! 18971: rc = process_input(&data);
1.2 misho 18972: }
18973: }
18974: set_table_name(&data, 0);
18975: if( data.db ){
1.4 misho 18976: session_close_all(&data);
1.4.2.2 ! misho 18977: close_db(data.db);
1.2 misho 18978: }
1.4 misho 18979: sqlite3_free(data.zFreeOnClose);
1.4.2.1 misho 18980: find_home_dir(1);
1.4.2.2 ! misho 18981: output_reset(&data);
! 18982: data.doXdgOpen = 0;
! 18983: clearTempFile(&data);
1.4 misho 18984: #if !SQLITE_SHELL_IS_UTF8
1.4.2.2 ! misho 18985: for(i=0; i<argcToFree; i++) free(argvToFree[i]);
! 18986: free(argvToFree);
1.4 misho 18987: #endif
1.4.2.2 ! misho 18988: /* Clear the global data structure so that valgrind will detect memory
! 18989: ** leaks */
! 18990: memset(&data, 0, sizeof(data));
1.2 misho 18991: return rc;
18992: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>